diff --git a/.github/workflows/build_and_functional_tests.yml b/.github/workflows/build_and_functional_tests.yml index 65ebfa0cd0..895de2e2d1 100644 --- a/.github/workflows/build_and_functional_tests.yml +++ b/.github/workflows/build_and_functional_tests.yml @@ -15,7 +15,7 @@ on: type: choice required: true default: 'Raise an error (default)' - description: CI behavior if the test snaphots are different than expected. + description: CI behavior if the test snapshots are different than expected. options: - 'Raise an error (default)' - 'Open a PR' @@ -59,5 +59,5 @@ jobs: download_app_binaries_artifact: "ragger_elfs" additional_app_binaries_artifact: "clone_elfs" additional_app_binaries_artifact_dir: ./tests/ragger/.test_dependencies/clone/build/ - test_options: "--with_lib_mode" + test_options: "--setup lib_mode" regenerate_snapshots: ${{ inputs.golden_run == 'Open a PR' }} diff --git a/.github/workflows/cflite_cron.yml b/.github/workflows/cflite_cron.yml index 440a752f5c..f86b15473b 100644 --- a/.github/workflows/cflite_cron.yml +++ b/.github/workflows/cflite_cron.yml @@ -35,6 +35,6 @@ jobs: uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} - fuzz-seconds: 300 # 5 minutes + fuzz-seconds: 900 # 15 minutes mode: ${{ matrix.mode }} sanitizer: ${{ matrix.sanitizer }} diff --git a/.github/workflows/codeql_checks.yml b/.github/workflows/codeql_checks.yml index 7b492d9134..ff23164336 100644 --- a/.github/workflows/codeql_checks.yml +++ b/.github/workflows/codeql_checks.yml @@ -24,7 +24,7 @@ jobs: language: ['cpp'] runs-on: ubuntu-latest container: - image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest + image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest steps: - name: Clone diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index c591393b9c..27c9805316 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -23,4 +23,4 @@ jobs: with: builtin: clear,rare check_filenames: true - path: src, src_bagl, src_features, src_nbgl, src_plugin_sdk, src_plugins, doc, client + path: src, src_bagl, src_features, src_nbgl, src_plugins, doc, client diff --git a/.gitignore b/.gitignore index ed206c628d..84b800f2cf 100644 --- a/.gitignore +++ b/.gitignore @@ -19,8 +19,12 @@ __version__.py # Fuzzing tests/fuzzing/corpus/ tests/fuzzing/out/ +tests/fuzzing/CMakeFiles/ default.profraw default.profdata fuzz-*.log crash-* report.html + +# LSP +.cache/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 06afa812d5..764c270661 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -14,7 +14,7 @@ repos: - id: check-case-conflict - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 + rev: v2.3.0 hooks: - id: codespell args: ['--ignore-words-list', 'ontop,shft,hte', '--skip', 'makefile_conf/chain/*,tests/ragger/eip712_input_files/*'] @@ -26,7 +26,7 @@ repos: types_or: [c] - repo: https://github.com/Mateusz-Grzelinski/actionlint-py - rev: v1.6.27.13 + rev: v1.7.6.22 hooks: - id: actionlint types_or: [yaml] @@ -39,9 +39,10 @@ repos: types_or: [markdown] - repo: https://github.com/PyCQA/pylint - rev: v2.16.2 + rev: v3.3.3 hooks: - id: pylint + language: system types: [python] args: ['--jobs=0', '--rcfile=tests/ragger/setup.cfg'] files: '^tests/ragger/.*$' diff --git a/CHANGELOG.md b/CHANGELOG.md index f3ec327cd8..4ddb2ba492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,22 @@ 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.16.0](../../compare/1.15.0...1.16.0) - 2025-04-28 + +### Added + +- (network) Berachain +- Transaction check +- Support for proxy contract clear-signing +- New clear-signing formatter for token ticker (without an amount) + +### Changed + +- The calldata is now compressed in RAM, enabling the support of even larger transactions +- Fixed values of trusted names key IDs +- Improved error handling with plugins +- Moved button to see contract info to the first key-value pair (Flex/Stax) + ## [1.15.0](../../compare/1.14.0...1.15.0) - 2025-01-30 ### Added diff --git a/Makefile b/Makefile index 5fb269659e..c79ff04cfd 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ endif include ./makefile_conf/chain/$(CHAIN).mk APPVERSION_M = 1 -APPVERSION_N = 15 +APPVERSION_N = 16 APPVERSION_P = 0 APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) @@ -103,12 +103,6 @@ PATH_APP_LOAD_PARAMS += "45'" "44'/1'" VARIANT_PARAM = CHAIN VARIANT_VALUES = $(SUPPORTED_CHAINS) -# Activate dependency only for specific CHAIN -ifneq ($(CHAIN),ethereum) - DEP_APP_LOAD_PARAMS = Ethereum:$(APPVERSION) - DEFINES_LIB = USE_LIB_ETHEREUM -endif - # Enabling DEBUG flag will enable PRINTF and disable optimizations #DEBUG = 1 @@ -117,14 +111,22 @@ endif ######################################## # See SDK `include/appflags.h` for the purpose of each permission #HAVE_APPLICATION_FLAG_DERIVE_MASTER = 1 -HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 -HAVE_APPLICATION_FLAG_BOLOS_SETTINGS = 1 -HAVE_APPLICATION_FLAG_LIBRARY = 1 +#HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 +#HAVE_APPLICATION_FLAG_BOLOS_SETTINGS = 1 +ifeq ($(CHAIN),ethereum) + HAVE_APPLICATION_FLAG_LIBRARY = 1 +else + # Activate dependency only for specific CHAIN + DEP_APP_LOAD_PARAMS = Ethereum:$(APPVERSION) + DEFINES_LIB = USE_LIB_ETHEREUM +endif + ######################################## # Application communication interfaces # ######################################## ENABLE_BLUETOOTH = 1 +ENABLE_SWAP = 1 #ENABLE_NFC = 1 ######################################## diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index 4a48015977..381826273d 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -1,19 +1,22 @@ -import rlp import struct from enum import IntEnum +from typing import Optional, Tuple +from hashlib import sha256 +import rlp +from web3 import Web3 +from eth_utils import keccak + from ragger.backend import BackendInterface from ragger.firmware import Firmware from ragger.error import ExceptionRAPDU from ragger.utils import RAPDU -from typing import Optional from .command_builder import CommandBuilder from .eip712 import EIP712FieldType from .keychain import sign_data, Key -from .tlv import format_tlv - -from hashlib import sha256 -from web3 import Web3 +from .tlv import format_tlv, FieldTag +from .response_parser import pk_addr +from .tx_simu import TxSimu class StatusWord(IntEnum): @@ -44,27 +47,6 @@ class TrustedNameSource(IntEnum): DNS = 0x05 -class FieldTag(IntEnum): - STRUCT_TYPE = 0x01 - STRUCT_VERSION = 0x02 - NOT_VALID_AFTER = 0x10 - CHALLENGE = 0x12 - SIGNER_KEY_ID = 0x13 - SIGNER_ALGO = 0x14 - DER_SIGNATURE = 0x15 - TRUSTED_NAME = 0x20 - COIN_TYPE = 0x21 - ADDRESS = 0x22 - CHAIN_ID = 0x23 - TICKER = 0x24 - BLOCKCHAIN_FAMILY = 0x51 - NETWORK_NAME = 0x52 - NETWORK_ICON_HASH = 0x53 - TRUSTED_NAME_TYPE = 0x70 - TRUSTED_NAME_SOURCE = 0x71 - TRUSTED_NAME_NFT_ID = 0x72 - - class PKIPubKeyUsage(IntEnum): PUBKEY_USAGE_GENUINE_CHECK = 0x01 PUBKEY_USAGE_EXCHANGE_PAYLOAD = 0x02 @@ -75,6 +57,7 @@ class PKIPubKeyUsage(IntEnum): PUBKEY_USAGE_PLUGIN_METADATA = 0x07 PUBKEY_USAGE_COIN_META = 0x08 PUBKEY_USAGE_SEED_ID_AUTH = 0x09 + PUBKEY_USAGE_TX_SIMU_SIGNER = 0x0a PUBKEY_USAGE_CALLDATA = 0x0b PUBKEY_USAGE_NETWORK = 0x0c @@ -92,7 +75,7 @@ class PKIClient: def __init__(self, client: BackendInterface) -> None: self._client = client - def send_certificate(self, p1: PKIPubKeyUsage, payload: bytes) -> RAPDU: + def send_certificate(self, p1: PKIPubKeyUsage, payload: bytes) -> None: try: response = self.send_raw(p1, payload) assert response.status == StatusWord.OK @@ -147,6 +130,9 @@ def send_raw_async(self, cla: int, ins: int, p1: int, p2: int, payload: bytes): header.append(len(payload)) return self._exchange_async(header + payload) + def get_app_configuration(self): + return self._exchange(self._cmd_builder.get_app_configuration()) + def eip712_send_struct_def_struct_name(self, name: str): return self._exchange_async(self._cmd_builder.eip712_send_struct_def_struct_name(name)) @@ -226,10 +212,9 @@ def eip712_filtering_trusted_name(self, def eip712_filtering_raw(self, name: str, sig: bytes, discarded: bool): return self._exchange_async(self._cmd_builder.eip712_filtering_raw(name, sig, discarded)) - def sign(self, - bip32_path: str, - tx_params: dict, - mode: SignMode = SignMode.BASIC): + def serialize_tx(self, tx_params: dict) -> Tuple[bytes, bytes]: + """Computes the serialized TX and its hash""" + tx = Web3().eth.account.create().sign_transaction(tx_params).rawTransaction prefix = bytes() suffix = [] @@ -239,8 +224,16 @@ def sign(self, else: # legacy if "chainId" in tx_params: suffix = [int(tx_params["chainId"]), bytes(), bytes()] - decoded = rlp.decode(tx)[:-3] # remove already computed signature - tx = prefix + rlp.encode(decoded + suffix) + decoded_tx = rlp.decode(tx)[:-3] # remove already computed signature + encoded_tx = prefix + rlp.encode(decoded_tx + suffix) + tx_hash = keccak(encoded_tx) + return encoded_tx, tx_hash + + def sign(self, + bip32_path: str, + tx_params: dict, + mode: SignMode = SignMode.BASIC): + tx, _ = self.serialize_tx(tx_params) chunks = self._cmd_builder.sign(bip32_path, tx, mode) for chunk in chunks[:-1]: self._exchange(chunk) @@ -253,7 +246,7 @@ def get_public_addr(self, display: bool = True, chaincode: bool = False, bip32_path: str = "m/44'/60'/0'/0/0", - chain_id: Optional[int] = None) -> RAPDU: + chain_id: Optional[int] = None): return self._exchange_async(self._cmd_builder.get_public_addr(display, chaincode, bip32_path, @@ -275,6 +268,7 @@ def perform_privacy_operation(self, def _provide_trusted_name_common(self, payload: bytes, name_source: TrustedNameSource) -> RAPDU: payload += format_tlv(FieldTag.STRUCT_TYPE, 3) # TrustedName + cert_apdu = "" if name_source == TrustedNameSource.CAL: if self._pki_client is not None: # pylint: disable=line-too-long @@ -286,8 +280,10 @@ def _provide_trusted_name_common(self, payload: bytes, name_source: TrustedNameS cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010415473045022100ABA9D58446EE81EB073DA91941989DD7E133556D58DE2BCBA59E46253DB448B102201DF8AE930A9E318B50576D8922503A5D3EC84C00C332A7C8FF7CD48708751840" # noqa: E501 elif self._firmware == Firmware.FLEX: cert_apdu = "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501051546304402206DC9F82C53F3B13400D3E343E3C8C81868E8C73B1EF2655D07891064B7AC3166022069A36E4059D75C93E488A5D58C02BCA9C80C081F77B31C5EDCF07F1A500C565A" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") # pylint: enable=line-too-long - key_id = 6 + key_id = 9 key = Key.CAL else: if self._pki_client is not None: @@ -300,11 +296,13 @@ def _provide_trusted_name_common(self, payload: bytes, name_source: TrustedNameS cert_apdu = "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010415473045022100A57DC7AB3F0E38A8D10783C7449024D929C60843BB75E5FF7B8088CB71CB130C022045A03E6F501F3702871466473BA08CE1F111357ED9EF395959733477165924C4" # noqa: E501 elif self._firmware == Firmware.FLEX: cert_apdu = "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010515473045022100D5BB77756C3D7C1B4254EA8D5351B94A89B13BA69C3631A523F293A10B7144B302201519B29A882BB22DCDDF6BE79A9CBA76566717FA877B7CA4B9CC40361A2D579E" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") # pylint: enable=line-too-long - key_id = 3 + key_id = 7 key = Key.TRUSTED_NAME - if self._pki_client is not None: + if self._pki_client is not None and cert_apdu: self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_TRUSTED_NAME, bytes.fromhex(cert_apdu)) payload += format_tlv(FieldTag.SIGNER_KEY_ID, key_id) # test key @@ -332,7 +330,7 @@ def provide_trusted_name_v2(self, chain_id: int, nft_id: Optional[int] = None, challenge: Optional[int] = None, - not_valid_after: Optional[tuple[int]] = None) -> RAPDU: + not_valid_after: Optional[Tuple[int]] = None) -> RAPDU: payload = format_tlv(FieldTag.STRUCT_VERSION, 2) payload += format_tlv(FieldTag.TRUSTED_NAME, name) payload += format_tlv(FieldTag.ADDRESS, addr) @@ -371,9 +369,12 @@ def set_plugin(self, cert_apdu = "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010415473045022100B8AF9667C190B60BF350D8F8CA66A4BCEA22BF47D757CB7F88F8D16C7794BCDC02205F7D6C8E9294F73744A82E1062B10FFEB809252682112E71A419EFC78227211B" # noqa: E501 elif self._firmware == Firmware.FLEX: cert_apdu = "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010515473045022100F5069D8BCEDCF7CC55273266E3871B09FFCACD084B5753347A809DDDA67E6235022003CE65364BFA96B6FE7A9D8C13EC87B8E727E8B7BF4A63176F5D61AB8F97807E" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") + cert_apdu = "" # pylint: enable=line-too-long - - self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_PLUGIN_METADATA, bytes.fromhex(cert_apdu)) + if cert_apdu: + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_PLUGIN_METADATA, bytes.fromhex(cert_apdu)) if sig is None: # Temporarily get a command with an empty signature to extract the payload and @@ -421,9 +422,12 @@ def provide_nft_metadata(self, cert_apdu = "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB3401013501041546304402201DEE04EC830FFDE5C98A708EC6865605FC14FF6105A54BE5230F2B954C673B940220581A0A5E42A7779140963703E43B3BEABE4C69284EDEF00E76BB5875E0810C9B" # noqa: E501 elif self._firmware == Firmware.FLEX: cert_apdu = "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB340101350105154730450221009ABCC7056D54C1B5DBB353178B13850C20521EE6884AA415AA61B329DB1D87F602204E308F273B8D18080184695438577F770524F717E5D08EE20ECBF1BC599F3538" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") + cert_apdu = "" # pylint: enable=line-too-long - - self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_NFT_METADATA, bytes.fromhex(cert_apdu)) + if cert_apdu: + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_NFT_METADATA, bytes.fromhex(cert_apdu)) if sig is None: # Temporarily get a command with an empty signature to extract the payload and @@ -489,9 +493,12 @@ def provide_token_metadata(self, cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501041546304402206731FCD3E2432C5CA162381392FD17AD3A41EEF852E1D706F21A656AB165263602204B89FAE8DBAF191E2D79FB00EBA80D613CB7EDF0BE960CB6F6B29D96E1437F5F" # noqa: E501 elif self._firmware == Firmware.FLEX: cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010515473045022100B59EA8B958AA40578A6FBE9BBFB761020ACD5DBD8AA863C11DA17F42B2AFDE790220186316059EFA58811337D47C7F815F772EA42BBBCEA4AE123D1118C80588F5CB" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") + cert_apdu = "" # pylint: enable=line-too-long - - self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu)) + if cert_apdu: + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu)) if sig is None: # Temporarily get a command with an empty signature to extract the payload and @@ -525,15 +532,14 @@ def _prepare_network_info(self, # Network Icon payload += format_tlv(FieldTag.NETWORK_ICON_HASH, sha256(icon).digest()) # Append the data Signature - payload += format_tlv(FieldTag.DER_SIGNATURE, - sign_data(Key.NETWORK, payload)) + payload += format_tlv(FieldTag.DER_SIGNATURE, sign_data(Key.NETWORK, payload)) return payload def provide_network_information(self, name: str, ticker: str, chain_id: int, - icon: Optional[bytes] = None) -> RAPDU: + icon: Optional[bytes] = None) -> None: if self._pki_client is None: print(f"Ledger-PKI Not supported on '{self._firmware.name}'") @@ -547,9 +553,12 @@ def provide_network_information(self, cert_apdu = "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010415463044022044C595C3E98100D4ECA75A73BF294090FF94948E80EE1430624C886B15BE862302200994E1D98CA72B78D57808B5FD236F439376AFC7C651B55D4AFBFB5AF4C15E00" # noqa: E501 elif self._firmware == Firmware.FLEX: cert_apdu = "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010515463044022008D276684F1A1CC3A89DB0B15120860414FF6A60E227FCAA29ED8F2096C982460220343FE956D443CEA33A2F8BD9DD1EAD783ACFF86088CF01BCE63C224DC815D7F0" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") + cert_apdu = "" # pylint: enable=line-too-long - - self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_NETWORK, bytes.fromhex(cert_apdu)) + if cert_apdu: + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_NETWORK, bytes.fromhex(cert_apdu)) # Add the network info payload = self._prepare_network_info(name, ticker, chain_id, icon) @@ -561,6 +570,21 @@ def provide_network_information(self, assert response.status == StatusWord.OK def provide_enum_value(self, payload: bytes) -> RAPDU: + if self._pki_client is None: + print(f"Ledger-PKI Not supported on '{self._firmware.name}'") + else: + # pylint: disable=line-too-long + if self._firmware == Firmware.NANOSP: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010315463044022076DD2EAB72E69D440D6ED8290C8C37E39F54294C23FF0F8520F836E7BE07455C02201D9A8A75223C1ADA1D9D00966A12EBB919D0BBF2E66F144C83FADCAA23672566" # noqa: E501 + elif self._firmware == Firmware.NANOX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010215463044022077FF9625006CB8A4AD41A4B04FF2112E92A732BD263CCE9B97D8E7D2536D04300220445B8EE3616FB907AA5E68359275E94D0A099C3E32A4FC8B3669C34083671F2F" # noqa: E501 + elif self._firmware == Firmware.STAX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010415473045022100A88646AD72CA012D5FDAF8F6AE0B7EBEF079212768D57323CB5B57CADD9EB20D022005872F8EA06092C9783F01AF02C5510588FB60CBF4BA51FB382B39C1E060BB6B" # noqa: E501 + elif self._firmware == Firmware.FLEX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B43401013501051546304402205305BDDDAD0284A2EAC2A9BE4CEF6604AE9415C5F46883448F5F6325026234A3022001ED743BCF33CCEB070FDD73C3D3FCC2CEE5AB30A5C3EB7D2A8D21C6F58D493F" # noqa: E501 + # pylint: enable=line-too-long + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_CALLDATA, bytes.fromhex(cert_apdu)) + chunks = self._cmd_builder.provide_enum_value(payload) for chunk in chunks[:-1]: self._exchange(chunk) @@ -579,10 +603,71 @@ def provide_transaction_info(self, payload: bytes) -> RAPDU: cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010415473045022100A88646AD72CA012D5FDAF8F6AE0B7EBEF079212768D57323CB5B57CADD9EB20D022005872F8EA06092C9783F01AF02C5510588FB60CBF4BA51FB382B39C1E060BB6B" # noqa: E501 elif self._firmware == Firmware.FLEX: cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B43401013501051546304402205305BDDDAD0284A2EAC2A9BE4CEF6604AE9415C5F46883448F5F6325026234A3022001ED743BCF33CCEB070FDD73C3D3FCC2CEE5AB30A5C3EB7D2A8D21C6F58D493F" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") + cert_apdu = "" # pylint: enable=line-too-long + if cert_apdu: + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_CALLDATA, bytes.fromhex(cert_apdu)) - self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_CALLDATA, bytes.fromhex(cert_apdu)) chunks = self._cmd_builder.provide_transaction_info(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()) + + def provide_tx_simulation(self, simu_params: TxSimu) -> RAPDU: + + if self._pki_client is None: + print(f"Ledger-PKI Not supported on '{self._firmware.name}'") + else: + # pylint: disable=line-too-long + if self._firmware == Firmware.NANOSP: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010315473045022100EABC9E26361DD551E30F52604884E5D0DAEF9EDD63848C45DA0B446DEE870BF002206AC308F46D04E5B23CC8D62F9C062E3AF931E3EEF9C2509AFA768A891CA8F10B" # noqa: E501 + elif self._firmware == Firmware.NANOX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010215473045022100B9EC810718F85C110CF60E7C5A8A6A4F783F3E0918E93861A8FCDCE7CFF4D405022047BD29E3F2B8EFD3FC7451FA19EE3147C38BEF83246DC396E7A10B2D2A44DB30" # noqa: E501 + elif self._firmware == Firmware.STAX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010415473045022100C490C9DD99F7D1A39D3AE9D448762DEAA17694C9BCF00454503498D2BA883DFE02204AEAD903C2B3A106206D7C2B1ACAA6DD20B6B41EE6AEF38F060F05EC4D7813BB" # noqa: E501 + elif self._firmware == Firmware.FLEX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010515473045022100FFDE724191BAA18250C7A93404D57CE13465797979EAF64239DB221BA679C5A402206E02953F47D32299F82616713D3DBA39CF8A09EF948B23446A6DDE610F80D066" # noqa: E501 + else: + print(f"Invalid device '{self._firmware.name}'") + cert_apdu = "" + # pylint: enable=line-too-long + if cert_apdu: + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_TX_SIMU_SIGNER, bytes.fromhex(cert_apdu)) + + if not simu_params.from_addr: + with self.get_public_addr(False): + pass + response = self.response() + assert response + _, from_addr, _ = pk_addr(response.data) + simu_params.from_addr = from_addr + + chunks = self._cmd_builder.provide_tx_simulation(simu_params.serialize()) + for chunk in chunks[:-1]: + self._exchange(chunk) + return self._exchange(chunks[-1]) + + def provide_proxy_info(self, payload: bytes) -> RAPDU: + if self._pki_client is None: + print(f"Ledger-PKI Not supported on '{self._firmware.name}'") + else: + # pylint: disable=line-too-long + if self._firmware == Firmware.NANOSP: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010315463044022076DD2EAB72E69D440D6ED8290C8C37E39F54294C23FF0F8520F836E7BE07455C02201D9A8A75223C1ADA1D9D00966A12EBB919D0BBF2E66F144C83FADCAA23672566" # noqa: E501 + elif self._firmware == Firmware.NANOX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010215463044022077FF9625006CB8A4AD41A4B04FF2112E92A732BD263CCE9B97D8E7D2536D04300220445B8EE3616FB907AA5E68359275E94D0A099C3E32A4FC8B3669C34083671F2F" # noqa: E501 + elif self._firmware == Firmware.STAX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010415473045022100A88646AD72CA012D5FDAF8F6AE0B7EBEF079212768D57323CB5B57CADD9EB20D022005872F8EA06092C9783F01AF02C5510588FB60CBF4BA51FB382B39C1E060BB6B" # noqa: E501 + elif self._firmware == Firmware.FLEX: + cert_apdu = "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B43401013501051546304402205305BDDDAD0284A2EAC2A9BE4CEF6604AE9415C5F46883448F5F6325026234A3022001ED743BCF33CCEB070FDD73C3D3FCC2CEE5AB30A5C3EB7D2A8D21C6F58D493F" # noqa: E501 + # pylint: enable=line-too-long + self._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_CALLDATA, bytes.fromhex(cert_apdu)) + chunks = self._cmd_builder.provide_proxy_info(payload) + for chunk in chunks[:-1]: + self._exchange(chunk) + return self._exchange(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 090833dd86..cee5eea80c 100644 --- a/client/src/ledger_app_clients/ethereum/command_builder.py +++ b/client/src/ledger_app_clients/ethereum/command_builder.py @@ -3,7 +3,7 @@ import struct from enum import IntEnum -from typing import List, Optional +from typing import Optional from ragger.bip import pack_derivation_path from .eip712 import EIP712FieldType @@ -13,6 +13,7 @@ class InsType(IntEnum): GET_PUBLIC_ADDR = 0x02 GET_ETH2_PUBLIC_ADDR = 0x0e SIGN = 0x04 + GET_APP_CONFIGURATION = 0x06 PERSONAL_SIGN = 0x08 PROVIDE_ERC20_TOKEN_INFORMATION = 0x0a EXTERNAL_PLUGIN_SETUP = 0x12 @@ -27,7 +28,9 @@ class InsType(IntEnum): PROVIDE_TRUSTED_NAME = 0x22 PROVIDE_ENUM_VALUE = 0x24 PROVIDE_TRANSACTION_INFO = 0x26 + PROVIDE_PROXY_INFO = 0x2a PROVIDE_NETWORK_INFORMATION = 0x30 + PROVIDE_TX_SIMULATION = 0x32 class P1Type(IntEnum): @@ -37,6 +40,7 @@ class P1Type(IntEnum): SIGN_SUBSQT_CHUNK = 0x80 FIRST_CHUNK = 0x01 FOLLOWING_CHUNK = 0x00 + OPT_IN_W3C = 0x01 class P2Type(IntEnum): @@ -80,6 +84,11 @@ def eip712_send_struct_def_struct_name(self, name: str) -> bytes: P2Type.STRUCT_NAME, name.encode()) + def get_app_configuration(self) -> bytes: + return self._serialize(InsType.GET_APP_CONFIGURATION, + 0x00, + 0x00) + def eip712_send_struct_def_struct_field(self, field_type: EIP712FieldType, type_name: str, @@ -125,7 +134,7 @@ def eip712_send_struct_impl_array(self, size: int) -> bytes: data) def eip712_send_struct_impl_struct_field(self, data: bytearray) -> list[bytes]: - chunks = list() + 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) @@ -264,7 +273,7 @@ def set_external_plugin(self, plugin_name: str, contract_address: bytes, selecto data) def sign(self, bip32_path: str, rlp_data: bytes, p2: int) -> list[bytes]: - apdus = list() + apdus = [] payload = pack_derivation_path(bip32_path) payload += rlp_data p1 = P1Type.SIGN_FIRST_CHUNK @@ -281,7 +290,7 @@ def get_challenge(self) -> bytes: return self._serialize(InsType.GET_CHALLENGE, 0x00, 0x00) def provide_trusted_name(self, tlv_payload: bytes) -> list[bytes]: - chunks = list() + chunks = [] payload = struct.pack(">H", len(tlv_payload)) payload += tlv_payload p1 = 1 @@ -376,7 +385,7 @@ def personal_sign(self, path: str, msg: bytes): payload = pack_derivation_path(path) payload += struct.pack(">I", len(msg)) payload += msg - chunks = list() + chunks = [] p1 = P1Type.SIGN_FIRST_CHUNK while len(payload) > 0: chunk_size = 0xff @@ -406,18 +415,35 @@ def provide_erc20_token_information(self, 0x00, payload) + def common_tlv_serialize(self, + ins: InsType, + tlv_payload: bytes, + p1l: list[int] = [0x01, 0x00], + p2l: list[int] = [0x00]) -> list[bytes]: + assert len(p1l) in [1, 2] + assert len(p2l) in [1, 2] + chunks = [] + payload = struct.pack(">H", len(tlv_payload)) + payload += tlv_payload + p1 = p1l[0] + p2 = p2l[0] + while len(payload) > 0: + chunks.append(self._serialize(ins, + p1, + p2, + payload[:0xff])) + payload = payload[0xff:] + # -1 so it works with a list of 1 or 2 items + p1 = p1l[-1] + p2 = p2l[-1] + return chunks + def provide_network_information(self, tlv_payload: bytes, icon: Optional[bytes] = None) -> list[bytes]: - chunks: List[bytes] = [] - - # Check if the TLV payload is larger than 0xff - assert len(tlv_payload) < 0xff, "Payload too large" - # Serialize the payload - chunks.append(self._serialize(InsType.PROVIDE_NETWORK_INFORMATION, - 0x00, - P2Type.NETWORK_CONFIG, - tlv_payload)) + chunks = self.common_tlv_serialize(InsType.PROVIDE_NETWORK_INFORMATION, + tlv_payload, + p2l=[P2Type.NETWORK_CONFIG]) if icon: p1 = P1Type.FIRST_CHUNK @@ -430,22 +456,18 @@ def provide_network_information(self, p1 = P1Type.FOLLOWING_CHUNK return chunks - def common_tlv_serialize(self, tlv_payload: bytes, ins: InsType) -> list[bytes]: - chunks = list() - payload = struct.pack(">H", len(tlv_payload)) - payload += tlv_payload - p1 = 1 - while len(payload) > 0: - chunks.append(self._serialize(ins, - p1, - 0x00, - payload[:0xff])) - payload = payload[0xff:] - p1 = 0 - return chunks - def provide_enum_value(self, tlv_payload: bytes) -> list[bytes]: - return self.common_tlv_serialize(tlv_payload, InsType.PROVIDE_ENUM_VALUE) + return self.common_tlv_serialize(InsType.PROVIDE_ENUM_VALUE, tlv_payload) def provide_transaction_info(self, tlv_payload: bytes) -> list[bytes]: - return self.common_tlv_serialize(tlv_payload, InsType.PROVIDE_TRANSACTION_INFO) + return self.common_tlv_serialize(InsType.PROVIDE_TRANSACTION_INFO, tlv_payload) + + def opt_in_tx_simulation(self) -> bytes: + # Serialize the payload + return self._serialize(InsType.PROVIDE_TX_SIMULATION, P1Type.OPT_IN_W3C, 0x00) + + def provide_tx_simulation(self, tlv_payload: bytes) -> list[bytes]: + return self.common_tlv_serialize(InsType.PROVIDE_TX_SIMULATION, tlv_payload, p1l=[0x00], p2l=[0x01, 0x00]) + + def provide_proxy_info(self, tlv_payload: bytes) -> list[bytes]: + return self.common_tlv_serialize(InsType.PROVIDE_PROXY_INFO, tlv_payload) diff --git a/client/src/ledger_app_clients/ethereum/eip712/InputData.py b/client/src/ledger_app_clients/ethereum/eip712/InputData.py index c83e37ef93..b868ca7c43 100644 --- a/client/src/ledger_app_clients/ethereum/eip712/InputData.py +++ b/client/src/ledger_app_clients/ethereum/eip712/InputData.py @@ -7,13 +7,13 @@ from typing import Any, Callable, Optional, Union import struct -from client import keychain -from client.client import EthAppClient, EIP712FieldType - from ragger.firmware import Firmware +from client import keychain +from client.client import EthAppClient, EIP712FieldType from client.client import PKIPubKeyUsage + # global variables app_client: EthAppClient = None filtering_paths: dict = {} @@ -34,7 +34,7 @@ def default_handler(): # Input = "uint8[2][][4]" | "bool" # Output = ('uint8', [2, None, 4]) | ('bool', []) def get_array_levels(typename): - array_lvls = list() + array_lvls = [] regex = re.compile(r"(.*)\[([0-9]*)\]$") while True: @@ -109,7 +109,7 @@ def send_struct_def_field(typename, keyname): (typename, array_lvls) = get_array_levels(typename) (typename, typesize) = get_typesize(typename) - if typename in parsing_type_functions.keys(): + if typename in parsing_type_functions: (type_enum, typesize) = parsing_type_functions[typename](typesize) else: type_enum = EIP712FieldType.CUSTOM @@ -278,8 +278,7 @@ def evaluate_field(structs, data, field, lvls_left, new_level=True): idx += 1 if array_lvls[lvls_left - 1] is not None: if array_lvls[lvls_left - 1] != idx: - print("Mismatch in array size! Got %d, expected %d\n" % - (idx, array_lvls[lvls_left - 1]), + print(f"Mismatch in array size! Got {idx}, expected {array_lvls[lvls_left - 1]}\n", file=sys.stderr) return False else: @@ -298,8 +297,7 @@ def send_struct_impl(structs, data, structname): if structname not in structs.keys(): return False - struct = structs[structname] - for f in struct: + for f in structs[structname]: if not evaluate_field(structs, data[f["name"]], f, len(f["array_lvls"])): return False return True @@ -318,8 +316,6 @@ def start_signature_payload(ctx: dict, magic: int) -> bytearray: # ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures def send_filtering_message_info(display_name: str, filters_count: int): - global sig_ctx - to_sign = start_signature_payload(sig_ctx, 183) to_sign.append(filters_count) to_sign += display_name.encode() @@ -331,8 +327,6 @@ def send_filtering_message_info(display_name: str, filters_count: int): def send_filtering_amount_join_token(path: str, token_idx: int, discarded: bool): - global sig_ctx - to_sign = start_signature_payload(sig_ctx, 11) to_sign += path.encode() to_sign.append(token_idx) @@ -342,8 +336,6 @@ def send_filtering_amount_join_token(path: str, token_idx: int, discarded: bool) def send_filtering_amount_join_value(path: str, token_idx: int, display_name: str, discarded: bool): - global sig_ctx - to_sign = start_signature_payload(sig_ctx, 22) to_sign += path.encode() to_sign += display_name.encode() @@ -354,8 +346,6 @@ def send_filtering_amount_join_value(path: str, token_idx: int, display_name: st def send_filtering_datetime(path: str, display_name: str, discarded: bool): - global sig_ctx - to_sign = start_signature_payload(sig_ctx, 33) to_sign += path.encode() to_sign += display_name.encode() @@ -369,8 +359,6 @@ def send_filtering_trusted_name(path: str, name_type: list[int], name_source: list[int], discarded: bool): - global sig_ctx - to_sign = start_signature_payload(sig_ctx, 44) to_sign += path.encode() to_sign += display_name.encode() @@ -385,8 +373,6 @@ def send_filtering_trusted_name(path: str, # ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures def send_filtering_raw(path: str, display_name: str, discarded: bool): - global sig_ctx - to_sign = start_signature_payload(sig_ctx, 72) to_sign += path.encode() to_sign += display_name.encode() @@ -395,7 +381,7 @@ def send_filtering_raw(path: str, display_name: str, discarded: bool): pass -def prepare_filtering(filtr_data, message): +def prepare_filtering(filtr_data): global filtering_paths global filtering_tokens @@ -420,11 +406,12 @@ def handle_optional_domain_values(domain): domain["verifyingContract"] = "0x0000000000000000000000000000000000000000" -def init_signature_context(types, domain): - global sig_ctx - +def init_signature_context(types, domain, filters): handle_optional_domain_values(domain) - caddr = domain["verifyingContract"] + if "address" in filters: + caddr = filters["address"] + else: + caddr = domain["verifyingContract"] if caddr.startswith("0x"): caddr = caddr[2:] sig_ctx["caddr"] = bytearray.fromhex(caddr) @@ -444,7 +431,7 @@ def next_timeout(_signum: int, _frame): def enable_autonext(): if app_client._client.firmware in (Firmware.STAX, Firmware.FLEX): - delay = 1/3 + delay = 1/2 else: delay = 1/4 @@ -465,11 +452,12 @@ def process_data(aclient: EthAppClient, filters: Optional[dict] = None, autonext: Optional[Callable] = None, golden_run: bool = False) -> bool: - global sig_ctx global app_client global autonext_handler global is_golden_run + global current_path + current_path = [] # deepcopy because this function modifies the dict data_json = copy.deepcopy(data_json) app_client = aclient @@ -486,7 +474,7 @@ def process_data(aclient: EthAppClient, is_golden_run = golden_run if filters: - init_signature_context(types, domain) + init_signature_context(types, domain, filters) # send types definition for key in types.keys(): @@ -499,7 +487,7 @@ def process_data(aclient: EthAppClient, if filters: with app_client.eip712_filtering_activate(): pass - prepare_filtering(filters, message) + prepare_filtering(filters) if aclient._pki_client is None: print(f"Ledger-PKI Not supported on '{aclient._firmware.name}'") @@ -513,9 +501,12 @@ def process_data(aclient: EthAppClient, cert_apdu = "0101010201021104000000021201001302000214010116040000000020104549503731325F46696C746572696E67300200053101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501041546304402204EA7B30F0EEFEF25FAB3ADDA6609E25296C41DD1C5969A92FAE6B600AAC2902E02206212054E123F5F965F787AE7EE565E243F21B11725626D3FF058522D6BDCD995" # noqa: E501 elif aclient._firmware == Firmware.FLEX: cert_apdu = "0101010201021104000000021201001302000214010116040000000020104549503731325F46696C746572696E67300200053101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501051546304402205FB5E970065A95C57F00FFA3964946251815527613724ED6745C37E303934BE702203CC9F4124B42806F0A7CA765CFAB5AADEB280C35AB8F809FC49ADC97D9B9CE15" # noqa: E501 + else: + print(f"Invalid device '{aclient._firmware.name}'") + cert_apdu = "" # pylint: enable=line-too-long - - aclient._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu)) + if cert_apdu: + aclient._pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META, bytes.fromhex(cert_apdu)) # send domain implementation with app_client.eip712_send_struct_impl_root_struct(domain_typename): diff --git a/client/src/ledger_app_clients/ethereum/eip712/struct.py b/client/src/ledger_app_clients/ethereum/eip712/struct.py index 19dbacc570..fb0785ee82 100644 --- a/client/src/ledger_app_clients/ethereum/eip712/struct.py +++ b/client/src/ledger_app_clients/ethereum/eip712/struct.py @@ -2,7 +2,7 @@ class EIP712FieldType(IntEnum): - CUSTOM = 0, + CUSTOM = 0 INT = auto() UINT = auto() ADDRESS = auto() diff --git a/client/src/ledger_app_clients/ethereum/enum_value.py b/client/src/ledger_app_clients/ethereum/enum_value.py index 84febcfa29..d7eab077a8 100644 --- a/client/src/ledger_app_clients/ethereum/enum_value.py +++ b/client/src/ledger_app_clients/ethereum/enum_value.py @@ -1,6 +1,6 @@ from enum import IntEnum from typing import Optional -from .tlv import format_tlv +from .tlv import TlvSerializable from .keychain import sign_data, Key @@ -15,7 +15,7 @@ class Tag(IntEnum): SIGNATURE = 0xff -class EnumValue: +class EnumValue(TlvSerializable): version: int chain_id: int contract_addr: bytes @@ -45,15 +45,15 @@ def __init__(self, def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(Tag.VERSION, self.version) - payload += format_tlv(Tag.CHAIN_ID, self.chain_id) - payload += format_tlv(Tag.CONTRACT_ADDR, self.contract_addr) - payload += format_tlv(Tag.SELECTOR, self.selector) - payload += format_tlv(Tag.ID, self.id) - payload += format_tlv(Tag.VALUE, self.value) - payload += format_tlv(Tag.NAME, self.name) + payload += self.serialize_field(Tag.VERSION, self.version) + payload += self.serialize_field(Tag.CHAIN_ID, self.chain_id) + payload += self.serialize_field(Tag.CONTRACT_ADDR, self.contract_addr) + payload += self.serialize_field(Tag.SELECTOR, self.selector) + payload += self.serialize_field(Tag.ID, self.id) + payload += self.serialize_field(Tag.VALUE, self.value) + payload += self.serialize_field(Tag.NAME, self.name) sig = self.signature if sig is None: - sig = sign_data(Key.CAL, payload) - payload += format_tlv(Tag.SIGNATURE, sig) + sig = sign_data(Key.CALLDATA, payload) + payload += self.serialize_field(Tag.SIGNATURE, sig) return payload diff --git a/client/src/ledger_app_clients/ethereum/gcs.py b/client/src/ledger_app_clients/ethereum/gcs.py index 3913b22231..0890ec9af2 100644 --- a/client/src/ledger_app_clients/ethereum/gcs.py +++ b/client/src/ledger_app_clients/ethereum/gcs.py @@ -2,12 +2,12 @@ from enum import IntEnum import struct -from .tlv import format_tlv +from .tlv import TlvSerializable from .keychain import sign_data, Key from .client import TrustedNameType, TrustedNameSource -class TxInfo(): +class TxInfo(TlvSerializable): version: int chain_id: int contract_addr: bytes @@ -49,26 +49,26 @@ def __init__(self, def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.chain_id) - payload += format_tlv(0x02, self.contract_addr) - payload += format_tlv(0x03, self.selector) - payload += format_tlv(0x04, self.fields_hash) - payload += format_tlv(0x05, self.operation_type) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.chain_id) + payload += self.serialize_field(0x02, self.contract_addr) + payload += self.serialize_field(0x03, self.selector) + payload += self.serialize_field(0x04, self.fields_hash) + payload += self.serialize_field(0x05, self.operation_type) if self.creator_name is not None: - payload += format_tlv(0x06, self.creator_name) + payload += self.serialize_field(0x06, self.creator_name) if self.creator_legal_name is not None: - payload += format_tlv(0x07, self.creator_legal_name) + payload += self.serialize_field(0x07, self.creator_legal_name) if self.creator_url is not None: - payload += format_tlv(0x08, self.creator_url) + payload += self.serialize_field(0x08, self.creator_url) if self.contract_name is not None: - payload += format_tlv(0x09, self.contract_name) + payload += self.serialize_field(0x09, self.contract_name) if self.deploy_date is not None: - payload += format_tlv(0x0a, self.deploy_date) + payload += self.serialize_field(0x0a, self.deploy_date) signature = self.signature if signature is None: signature = sign_data(Key.CALLDATA, payload) - payload += format_tlv(0xff, signature) + payload += self.serialize_field(0xff, signature) return payload @@ -83,6 +83,7 @@ class ParamType(IntEnum): ENUM = 0x07 TRUSTED_NAME = 0x08 CALLDATA = 0x09 + TOKEN = 0x0a class TypeFamily(IntEnum): @@ -96,7 +97,7 @@ class TypeFamily(IntEnum): STRING = 0x08 -class PathTuple: +class PathTuple(TlvSerializable): value: int def __init__(self, value: int): @@ -106,7 +107,7 @@ def serialize(self) -> bytes: return struct.pack(">H", self.value) -class PathArray: +class PathArray(TlvSerializable): weight: int start: Optional[int] end: Optional[int] @@ -121,15 +122,15 @@ def __init__(self, def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x01, self.weight) + payload += self.serialize_field(0x01, self.weight) if self.start is not None: - payload += format_tlv(0x02, struct.pack(">h", self.start)) + payload += self.serialize_field(0x02, struct.pack(">h", self.start)) if self.end is not None: - payload += format_tlv(0x03, struct.pack(">h", self.end)) + payload += self.serialize_field(0x03, struct.pack(">h", self.end)) return payload -class PathRef: +class PathRef(TlvSerializable): def __init__(self): pass @@ -144,7 +145,7 @@ class PathLeafType(IntEnum): DYNAMIC = 0x04 -class PathLeaf: +class PathLeaf(TlvSerializable): type: PathLeafType def __init__(self, type: PathLeafType): @@ -154,7 +155,7 @@ def serialize(self) -> bytes: return struct.pack("B", self.type) -class PathSlice: +class PathSlice(TlvSerializable): start: Optional[int] end: Optional[int] @@ -165,26 +166,23 @@ def __init__(self, start: Optional[int] = None, end: Optional[int] = None): def serialize(self) -> bytes: payload = bytearray() if self.start is not None: - payload += format_tlv(0x01, struct.pack(">h", self.start)) + payload += self.serialize_field(0x01, struct.pack(">h", self.start)) if self.end is not None: - payload += format_tlv(0x02, struct.pack(">h", self.end)) + payload += self.serialize_field(0x02, struct.pack(">h", self.end)) return payload -PathElement = PathTuple | PathArray | PathRef | PathLeaf | PathSlice - - -class DataPath: +class DataPath(TlvSerializable): version: int - path: list[PathElement] + path: list[TlvSerializable] - def __init__(self, version: int, path: list[PathElement]): + def __init__(self, version: int, path: list[TlvSerializable]): self.version = version self.path = path def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) + payload += self.serialize_field(0x00, self.version) for node in self.path: if isinstance(node, PathTuple): tag = 0x01 @@ -198,7 +196,7 @@ def serialize(self) -> bytes: tag = 0x05 else: assert False, f"Unknown path node type : {type(node)}" - payload += format_tlv(tag, node.serialize()) + payload += self.serialize_field(tag, node.serialize()) return payload @@ -208,7 +206,7 @@ class ContainerPath(IntEnum): VALUE = 0x02 -class Value: +class Value(TlvSerializable): version: int type_family: TypeFamily type_size: Optional[int] @@ -232,20 +230,20 @@ def __init__(self, def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.type_family) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.type_family) if self.type_size is not None: - payload += format_tlv(0x02, self.type_size) + payload += self.serialize_field(0x02, self.type_size) if self.data_path is not None: - payload += format_tlv(0x03, self.data_path.serialize()) + payload += self.serialize_field(0x03, self.data_path.serialize()) if self.container_path is not None: - payload += format_tlv(0x04, self.container_path) + payload += self.serialize_field(0x04, self.container_path) if self.constant is not None: - payload += format_tlv(0x05, self.constant) + payload += self.serialize_field(0x05, self.constant) return payload -class ParamRaw: +class ParamRaw(TlvSerializable): version: int value: Value @@ -255,12 +253,12 @@ def __init__(self, version: int, value: Value): def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.value.serialize()) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.value.serialize()) return payload -class ParamAmount: +class ParamAmount(TlvSerializable): version: int value: Value @@ -270,12 +268,12 @@ def __init__(self, version: int, value: Value): def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.value.serialize()) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.value.serialize()) return payload -class ParamTokenAmount: +class ParamTokenAmount(TlvSerializable): version: int value: Value token: Optional[Value] @@ -299,21 +297,21 @@ def __init__(self, def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.value.serialize()) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.value.serialize()) if self.token is not None: - payload += format_tlv(0x02, self.token.serialize()) + payload += self.serialize_field(0x02, self.token.serialize()) if self.native_currency is not None: for nat_cur in self.native_currency: - payload += format_tlv(0x03, nat_cur) + payload += self.serialize_field(0x03, nat_cur) if self.threshold is not None: - payload += format_tlv(0x04, self.threshold) + payload += self.serialize_field(0x04, self.threshold) if self.above_threshold_msg is not None: - payload += format_tlv(0x05, self.above_threshold_msg) + payload += self.serialize_field(0x05, self.above_threshold_msg) return payload -class ParamNFT(): +class ParamNFT(TlvSerializable): version: int id: Value collection: Value @@ -325,9 +323,9 @@ def __init__(self, version: int, id: Value, collection: Value): def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.id.serialize()) - payload += format_tlv(0x02, self.collection.serialize()) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.id.serialize()) + payload += self.serialize_field(0x02, self.collection.serialize()) return payload @@ -336,7 +334,7 @@ class DatetimeType(IntEnum): DT_BLOCKHEIGHT = 0x01 -class ParamDatetime(): +class ParamDatetime(TlvSerializable): version: int value: Value type: DatetimeType @@ -348,13 +346,13 @@ def __init__(self, version: int, value: Value, type: DatetimeType): def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.value.serialize()) - payload += format_tlv(0x02, self.type) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.value.serialize()) + payload += self.serialize_field(0x02, self.type) return payload -class ParamDuration(): +class ParamDuration(TlvSerializable): version: int value: Value @@ -364,12 +362,12 @@ def __init__(self, version: int, value: Value): def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.value.serialize()) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.value.serialize()) return payload -class ParamUnit(): +class ParamUnit(TlvSerializable): version: int value: Value base: str @@ -390,44 +388,54 @@ def __init__(self, def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.value.serialize()) - payload += format_tlv(0x02, self.base) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.value.serialize()) + payload += self.serialize_field(0x02, self.base) if self.decimals is not None: - payload += format_tlv(0x03, self.decimals) + payload += self.serialize_field(0x03, self.decimals) if self.prefix is not None: - payload += format_tlv(0x04, self.prefix) + payload += self.serialize_field(0x04, self.prefix) return payload -class ParamTrustedName(): +class ParamTrustedName(TlvSerializable): version: int value: Value types: list[TrustedNameType] sources: list[TrustedNameSource] + sender_addrs: Optional[list[bytes]] - def __init__(self, version: int, value: Value, types: list[TrustedNameType], sources: list[TrustedNameSource]): + def __init__(self, + version: int, + value: Value, + types: list[TrustedNameType], + sources: list[TrustedNameSource], + sender_addrs: Optional[list[bytes]] = None): self.version = version self.value = value self.types = types self.sources = sources + self.sender_addrs = sender_addrs def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.value.serialize()) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.value.serialize()) types = bytearray() for type in self.types: types.append(type) - payload += format_tlv(0x02, types) + payload += self.serialize_field(0x02, types) sources = bytearray() for source in self.sources: sources.append(source) - payload += format_tlv(0x03, sources) + payload += self.serialize_field(0x03, sources) + if self.sender_addrs is not None: + for addr in self.sender_addrs: + payload += self.serialize_field(0x04, addr) return payload -class ParamEnum(): +class ParamEnum(TlvSerializable): version: int id: int value: Value @@ -439,30 +447,39 @@ def __init__(self, version: int, id: int, value: Value): def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.id) - payload += format_tlv(0x02, self.value.serialize()) + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.id) + payload += self.serialize_field(0x02, self.value.serialize()) return payload -ParamUnion = ParamRaw | \ - ParamAmount | \ - ParamTokenAmount | \ - ParamNFT | \ - ParamDatetime | \ - ParamDuration | \ - ParamUnit | \ - ParamTrustedName | \ - ParamEnum +class ParamToken(TlvSerializable): + version: int + addr: Value + native_currency: Optional[list[bytes]] + + def __init__(self, version, addr: Value, native_currency: Optional[list[bytes]] = None): + self.version = version + self.addr = addr + self.native_currency = native_currency + + def serialize(self) -> bytes: + payload = bytearray() + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.addr.serialize()) + if self.native_currency is not None: + for nat_cur in self.native_currency: + payload += self.serialize_field(0x02, nat_cur) + return payload -class Field: +class Field(TlvSerializable): version: int name: str param_type: ParamType - param: ParamUnion + param: TlvSerializable - def __init__(self, version: int, name: str, param_type: ParamType, param: ParamUnion): + def __init__(self, version: int, name: str, param_type: ParamType, param: TlvSerializable): self.version = version self.name = name self.param_type = param_type @@ -470,8 +487,8 @@ def __init__(self, version: int, name: str, param_type: ParamType, param: ParamU def serialize(self) -> bytes: payload = bytearray() - payload += format_tlv(0x00, self.version) - payload += format_tlv(0x01, self.name) - payload += format_tlv(0x02, self.param_type) - payload += format_tlv(0x03, self.param.serialize()) + 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(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 b913c867aa..f34ea60560 100644 --- a/client/src/ledger_app_clients/ethereum/keychain.py +++ b/client/src/ledger_app_clients/ethereum/keychain.py @@ -1,8 +1,8 @@ import os import hashlib +from enum import Enum, auto from ecdsa import SigningKey from ecdsa.util import sigencode_der -from enum import Enum, auto # Private key PEM files have to be named the same (lowercase) as their corresponding enum entries @@ -14,22 +14,21 @@ class Key(Enum): NFT = auto() CALLDATA = auto() NETWORK = auto() + WEB3_CHECK = auto() -_keys: dict[Key, SigningKey] = dict() +_keys: dict[Key, SigningKey] = {} # Open the corresponding PEM file and load its key in the global dict def _init_key(key: Key): - global _keys - with open("%s/keychain/%s.pem" % (os.path.dirname(__file__), key.name.lower())) as pem_file: + with open(f"{os.path.dirname(__file__)}/keychain/{key.name.lower()}.pem", encoding="utf-8") as pem_file: _keys[key] = SigningKey.from_pem(pem_file.read(), hashlib.sha256) assert (key in _keys) and (_keys[key] is not None) # Generate a SECP256K1 signature of the given data with the given key def sign_data(key: Key, data: bytes) -> bytes: - global _keys if key not in _keys: _init_key(key) return _keys[key].sign_deterministic(data, sigencode=sigencode_der) diff --git a/client/src/ledger_app_clients/ethereum/keychain/web3_check.pem b/client/src/ledger_app_clients/ethereum/keychain/web3_check.pem new file mode 100644 index 0000000000..7d4739a8d9 --- /dev/null +++ b/client/src/ledger_app_clients/ethereum/keychain/web3_check.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIMmCRHsdqPLLjX1Hj3NLdGOQz+9ipwh+odapUaEjU+CyoAcGBSuBBAAK +oUQDQgAE2hVMl1EjkL390OIXhSPveySGt6fdW1BwedLzZBrvVQE+trk/qkO+gVYL +6GlWN7Iy1YibXnFLmvxVwM5oSwQamw== +-----END EC PRIVATE KEY----- diff --git a/client/src/ledger_app_clients/ethereum/proxy_info.py b/client/src/ledger_app_clients/ethereum/proxy_info.py new file mode 100644 index 0000000000..32359a05d2 --- /dev/null +++ b/client/src/ledger_app_clients/ethereum/proxy_info.py @@ -0,0 +1,54 @@ +from enum import IntEnum +from typing import Optional +from .tlv import TlvSerializable +from .keychain import sign_data, Key + + +class Tag(IntEnum): + STRUCT_TYPE = 0x01 + STRUCT_VERSION = 0x02 + CHALLENGE = 0x12 + ADDRESS = 0x22 + CHAIN_ID = 0x23 + SELECTOR = 0x28 + IMPL_ADDRESS = 0x29 + SIGNATURE = 0x15 + + +class ProxyInfo(TlvSerializable): + challenge: int + address: bytes + chain_id: int + selector: Optional[bytes] + impl_address: bytes + signature: Optional[bytes] + + def __init__(self, + challenge: int, + address: bytes, + chain_id: int, + impl_address: bytes, + selector: Optional[bytes] = None, + signature: Optional[bytes] = None): + self.challenge = challenge + self.address = address + self.chain_id = chain_id + self.selector = selector + self.impl_address = impl_address + self.signature = signature + + def serialize(self) -> bytes: + payload = bytearray() + payload += self.serialize_field(Tag.STRUCT_TYPE, 0x26) + payload += self.serialize_field(Tag.STRUCT_VERSION, 1) + payload += self.serialize_field(Tag.CHALLENGE, self.challenge) + payload += self.serialize_field(Tag.ADDRESS, self.address) + payload += self.serialize_field(Tag.CHAIN_ID, self.chain_id) + if self.selector is not None: + payload += self.serialize_field(Tag.SELECTOR, self.selector) + payload += self.serialize_field(Tag.IMPL_ADDRESS, self.impl_address) + sig = self.signature + if sig is None: + sig = sign_data(Key.CALLDATA, payload) + payload += self.serialize_field(Tag.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 25718b6dc3..cb7586fcd3 100644 --- a/client/src/ledger_app_clients/ethereum/settings.py +++ b/client/src/ledger_app_clients/ethereum/settings.py @@ -1,10 +1,11 @@ from enum import Enum, auto +from typing import Union from ragger.firmware import Firmware from ragger.navigator import Navigator, NavInsID, NavIns -from typing import Union class SettingID(Enum): + WEB3_CHECK = auto() BLIND_SIGNING = auto() VERBOSE_ENS = auto() NONCE = auto() @@ -13,13 +14,23 @@ class SettingID(Enum): def get_device_settings(firmware: Firmware) -> list[SettingID]: + """Get the list of settings available on the device""" if firmware == Firmware.NANOS: return [ SettingID.BLIND_SIGNING, SettingID.NONCE, SettingID.DEBUG_DATA, ] + if firmware.is_nano: + return [ + SettingID.BLIND_SIGNING, + SettingID.VERBOSE_ENS, + SettingID.NONCE, + SettingID.VERBOSE_EIP712, + SettingID.DEBUG_DATA, + ] return [ + SettingID.WEB3_CHECK, SettingID.BLIND_SIGNING, SettingID.VERBOSE_ENS, SettingID.NONCE, @@ -28,29 +39,53 @@ def get_device_settings(firmware: Firmware) -> list[SettingID]: ] -def get_setting_position(firmware: Firmware, setting_idx: int, per_page: int) -> tuple[int, int]: +def get_setting_position(firmware: Firmware, setting: SettingID) -> tuple[int, int, int]: + """Get the position of the setting on the device""" if firmware == Firmware.STAX: - screen_height = 672 # px - screen_width = 400 # px - header_height = 88 # px - footer_height = 92 # px + x = 350 else: - screen_height = 600 # px - screen_width = 480 # px - header_height = 96 # px - footer_height = 96 # px - - index_in_page = setting_idx % per_page - usable_height = screen_height - (header_height + footer_height) - setting_height = usable_height // per_page - offset = (setting_height * index_in_page) + (setting_height // 2) - return screen_width // 2, header_height + offset + x = 420 + if setting == SettingID.WEB3_CHECK: + if firmware == Firmware.STAX: + page, y = 0, 130 + else: + page, y = 0, 140 + elif setting == SettingID.BLIND_SIGNING: + if firmware == Firmware.STAX: + page, y = 0, 335 + else: + page, y = 0, 350 + elif setting == SettingID.VERBOSE_ENS: + if firmware == Firmware.STAX: + page, y = 1, 130 + else: + page, y = 1, 140 + elif setting == SettingID.NONCE: + if firmware == Firmware.STAX: + page, y = 1, 300 + else: + page, y = 1, 315 + elif setting == SettingID.VERBOSE_EIP712: + if firmware == Firmware.STAX: + page, y = 1, 445 + else: + page, y = 2, 140 + elif setting == SettingID.DEBUG_DATA: + if firmware == Firmware.STAX: + page, y = 2, 130 + else: + page, y = 2, 315 + else: + raise ValueError(f"Unknown setting: {setting}") + return page, x, y -def settings_toggle(firmware: Firmware, nav: Navigator, to_toggle: list[SettingID]): +def get_settings_moves(firmware: Firmware, + to_toggle: list[SettingID]) -> list[Union[NavIns, NavInsID]]: + """Get the navigation instructions to toggle the settings""" moves: list[Union[NavIns, NavInsID]] = [] settings = get_device_settings(firmware) - # Assume the app is on the home page + # Assume the app is on the 1st page of Settings if firmware.is_nano: moves += [NavInsID.RIGHT_CLICK] * 2 moves += [NavInsID.BOTH_CLICK] @@ -60,13 +95,24 @@ def settings_toggle(firmware: Firmware, nav: Navigator, to_toggle: list[SettingI moves += [NavInsID.RIGHT_CLICK] moves += [NavInsID.BOTH_CLICK] # Back else: + current_page = 0 moves += [NavInsID.USE_CASE_HOME_SETTINGS] - settings_per_page = 3 if firmware == Firmware.STAX else 2 for setting in settings: - setting_idx = settings.index(setting) - if (setting_idx > 0) and (setting_idx % settings_per_page) == 0: - moves += [NavInsID.USE_CASE_SETTINGS_NEXT] if setting in to_toggle: - moves += [NavIns(NavInsID.TOUCH, get_setting_position(firmware, setting_idx, settings_per_page))] + page, x, y = get_setting_position(firmware, setting) + moves += [NavInsID.USE_CASE_SETTINGS_NEXT] * (page - current_page) + moves += [NavIns(NavInsID.TOUCH, (x, y))] + if setting == SettingID.WEB3_CHECK: + # Assume Opt-In is not done, Add a confirmation step + moves += [NavInsID.USE_CASE_CHOICE_CONFIRM] + # Dismiss the notification + moves += [NavInsID.TAPPABLE_CENTER_TAP] + current_page = page moves += [NavInsID.USE_CASE_SETTINGS_MULTI_PAGE_EXIT] - nav.navigate(moves, screen_change_before_first_instruction=False) + return moves + + +def settings_toggle(firmware: Firmware, navigator: Navigator, to_toggle: list[SettingID]): + """Toggle the settings""" + moves = get_settings_moves(firmware, to_toggle) + navigator.navigate(moves, screen_change_before_first_instruction=False) diff --git a/client/src/ledger_app_clients/ethereum/tlv.py b/client/src/ledger_app_clients/ethereum/tlv.py index e7a5d4a897..56a98f1b0d 100644 --- a/client/src/ledger_app_clients/ethereum/tlv.py +++ b/client/src/ledger_app_clients/ethereum/tlv.py @@ -1,27 +1,65 @@ from typing import Union +from enum import IntEnum -def der_encode(value: int) -> bytes: - # max() to have minimum length of 1 - value_bytes = value.to_bytes(max(1, (value.bit_length() + 7) // 8), 'big') - if value >= 0x80: - value_bytes = (0x80 | len(value_bytes)).to_bytes(1, 'big') + value_bytes - return value_bytes +class FieldTag(IntEnum): + STRUCT_TYPE = 0x01 + STRUCT_VERSION = 0x02 + NOT_VALID_AFTER = 0x10 + CHALLENGE = 0x12 + SIGNER_KEY_ID = 0x13 + SIGNER_ALGO = 0x14 + DER_SIGNATURE = 0x15 + TRUSTED_NAME = 0x20 + COIN_TYPE = 0x21 + ADDRESS = 0x22 + CHAIN_ID = 0x23 + TICKER = 0x24 + TX_HASH = 0x27 + DOMAIN_HASH = 0x28 + BLOCKCHAIN_FAMILY = 0x51 + NETWORK_NAME = 0x52 + NETWORK_ICON_HASH = 0x53 + TRUSTED_NAME_TYPE = 0x70 + TRUSTED_NAME_SOURCE = 0x71 + TRUSTED_NAME_NFT_ID = 0x72 + W3C_NORMALIZED_RISK = 0x80 + W3C_NORMALIZED_CATEGORY = 0x81 + W3C_PROVIDER_MSG = 0x82 + W3C_TINY_URL = 0x83 + W3C_SIMULATION_TYPE = 0x84 -def format_tlv(tag: int, value: Union[int, str, bytes, bytearray]) -> bytes: - if isinstance(value, int): +class TlvSerializable: + def serialize(self) -> bytes: + raise NotImplementedError + + @staticmethod + def der_encode(value: int) -> bytes: # max() to have minimum length of 1 - value = value.to_bytes(max(1, (value.bit_length() + 7) // 8), 'big') - elif isinstance(value, str): - value = value.encode() - elif isinstance(value, bytearray): - value = bytes(value) - - assert isinstance(value, bytes), f"Unhandled TLV formatting for type : {type(value)}" - - tlv = bytearray() - tlv += der_encode(tag) - tlv += der_encode(len(value)) - tlv += value - return tlv + value_bytes = value.to_bytes(max(1, (value.bit_length() + 7) // 8), 'big') + if value >= 0x80: + value_bytes = (0x80 | len(value_bytes)).to_bytes(1, 'big') + value_bytes + return value_bytes + + @staticmethod + def serialize_field(tag: int, value: Union[int, str, bytes, bytearray]) -> bytes: + if isinstance(value, int): + # max() to have minimum length of 1 + value = value.to_bytes(max(1, (value.bit_length() + 7) // 8), 'big') + elif isinstance(value, str): + value = value.encode() + elif isinstance(value, bytearray): + value = bytes(value) + + assert isinstance(value, bytes), f"Unhandled TLV formatting for type : {type(value)}" + + tlv = bytearray() + tlv += TlvSerializable.der_encode(tag) + tlv += TlvSerializable.der_encode(len(value)) + tlv += value + return tlv + + +def format_tlv(tag: int, value: Union[int, str, bytes, bytearray]) -> bytes: + return TlvSerializable.serialize_field(tag, value) diff --git a/client/src/ledger_app_clients/ethereum/tx_simu.py b/client/src/ledger_app_clients/ethereum/tx_simu.py new file mode 100644 index 0000000000..8f3c54263f --- /dev/null +++ b/client/src/ledger_app_clients/ethereum/tx_simu.py @@ -0,0 +1,66 @@ +from typing import Optional +from enum import IntEnum + +from .tlv import TlvSerializable, FieldTag +from .keychain import sign_data, Key + + +class SimuType(IntEnum): + TRANSACTION = 0x00 + TYPED_DATA = 0x01 + PERSONAL_MESSAGE = 0x02 + + +class TxSimu(TlvSerializable): + simu_type: SimuType + risk: int + category: int + tiny_url: str + from_addr: Optional[bytes] = None + tx_hash: Optional[bytes] = None + chain_id: Optional[int] = None + domain_hash: Optional[bytes] = None + provider_message: Optional[str] + + def __init__(self, + simu_type: SimuType, + risk: int, + category: int, + tiny_url: str, + from_addr: Optional[bytes] = None, + tx_hash: Optional[bytes] = None, + chain_id: Optional[int] = None, + domain_hash: Optional[bytes] = None, + provider_message: Optional[str] = None) -> None: + self.simu_type = simu_type + self.from_addr = from_addr + self.tx_hash = tx_hash + self.risk = risk + self.category = category + self.tiny_url = tiny_url + self.chain_id = chain_id + self.domain_hash = domain_hash + self.provider_message = provider_message + + def serialize(self) -> bytes: + assert self.from_addr is not None, "From address is required" + assert self.tx_hash is not None, "Transaction hash is required" + # Construct the TLV payload + payload: bytes = self.serialize_field(FieldTag.STRUCT_TYPE, 9) + payload += self.serialize_field(FieldTag.STRUCT_VERSION, 1) + payload += self.serialize_field(FieldTag.W3C_SIMULATION_TYPE, self.simu_type) + payload += self.serialize_field(FieldTag.ADDRESS, self.from_addr) + payload += self.serialize_field(FieldTag.TX_HASH, self.tx_hash) + payload += self.serialize_field(FieldTag.W3C_NORMALIZED_RISK, self.risk) + payload += self.serialize_field(FieldTag.W3C_NORMALIZED_CATEGORY, self.category) + payload += self.serialize_field(FieldTag.W3C_TINY_URL, self.tiny_url.encode('utf-8')) + if self.chain_id: + payload += self.serialize_field(FieldTag.CHAIN_ID, self.chain_id.to_bytes(8, 'big')) + if self.domain_hash: + payload += self.serialize_field(FieldTag.DOMAIN_HASH, self.domain_hash) + if self.provider_message: + payload += self.serialize_field(FieldTag.W3C_PROVIDER_MSG, self.provider_message.encode('utf-8')) + + # Append the data Signature + payload += self.serialize_field(FieldTag.DER_SIGNATURE, sign_data(Key.WEB3_CHECK, payload)) + return payload diff --git a/client/src/ledger_app_clients/ethereum/utils.py b/client/src/ledger_app_clients/ethereum/utils.py index 0fa350840e..3b61e657b7 100644 --- a/client/src/ledger_app_clients/ethereum/utils.py +++ b/client/src/ledger_app_clients/ethereum/utils.py @@ -5,7 +5,7 @@ # eth_account requires it for some reason def normalize_vrs(vrs: tuple) -> tuple: - vrs_l = list() + vrs_l = [] for elem in vrs: vrs_l.append(elem.lstrip(b'\x00')) return tuple(vrs_l) diff --git a/doc/ethapp.adoc b/doc/ethapp.adoc index 058b89cf33..5aa82c3bfa 100644 --- a/doc/ethapp.adoc +++ b/doc/ethapp.adoc @@ -39,6 +39,7 @@ The following APDUs are managed by the application. They are detailed in the fol | GET CHALLENGE | 0x20 | PROVIDE DOMAIN NAME | 0x22 | PROVIDE NETWORK INFORMATION | 0x30 +| PROVIDE TX SIMULATION | 0x32 |============================================================================================================================== @@ -54,7 +55,7 @@ The address can be optionally checked on the device before being returned. #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -67,7 +68,7 @@ The address can be optionally checked on the device before being returned. 01 : return the chain code | variable | variable |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -79,7 +80,7 @@ The address can be optionally checked on the device before being returned. | Chain ID (big endian) (optional) | 8 |============================================================================================================================== -'Output data' +_Output data_ [width="80%"] |============================================================================================================================== @@ -87,7 +88,7 @@ The address can be optionally checked on the device before being returned. | Public Key length | 1 | Uncompressed Public Key | var | Ethereum address length | 1 -| Ethereum address | var +| ASCII-encoded Ethereum address | var | Chain code if requested | 32 |============================================================================================================================== @@ -109,7 +110,7 @@ The input data is the RLP encoded transaction (as per https://github.com/ethereu #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -124,7 +125,7 @@ The input data is the RLP encoded transaction (as per https://github.com/ethereu 02 : start flow | variable | variable |============================================================================================================================== -'Input data (first transaction data block)' +_Input data (first transaction data block)_ If P2 == 0x02, then no data is provided. @@ -138,7 +139,7 @@ If P2 == 0x02, then no data is provided. | RLP transaction chunk | variable |============================================================================================================================== -'Input data (other transaction data block)' +_Input data (other transaction data block)_ [width="80%"] |============================================================================================================================== @@ -147,7 +148,7 @@ If P2 == 0x02, then no data is provided. |============================================================================================================================== -'Output data' +_Output data_ If P2 == 0x01, then no data is returned. @@ -168,7 +169,7 @@ This command returns specific application configuration #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -176,11 +177,11 @@ This command returns specific application configuration | E0 | 06 | 00 | 00 | 00 | 04 |============================================================================================================================== -'Input data' +_Input data_ None -'Output data' +_Output data_ [width="80%"] |============================================================================================================================== @@ -189,6 +190,10 @@ None 0x01 : arbitrary data signature enabled by user 0x02 : ERC 20 Token information needs to be provided externally + + 0x10 : Web3 Check enabled + + 0x20 : Web3 Check Opt-In done | 01 | Application major version | 01 | Application minor version | 01 @@ -208,7 +213,7 @@ The input data is the message to sign, streamed to the device in 255 bytes maxim #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -219,7 +224,7 @@ The input data is the message to sign, streamed to the device in 255 bytes maxim | 00 | variable | variable |============================================================================================================================== -'Input data (first message data block)' +_Input data (first message data block)_ [width="80%"] |============================================================================================================================== @@ -232,7 +237,7 @@ The input data is the message to sign, streamed to the device in 255 bytes maxim | Message chunk | variable |============================================================================================================================== -'Input data (other transaction data block)' +_Input data (other transaction data block)_ [width="80%"] |============================================================================================================================== @@ -241,7 +246,7 @@ The input data is the message to sign, streamed to the device in 255 bytes maxim |============================================================================================================================== -'Output data' +_Output data_ [width="80%"] |============================================================================================================================== @@ -268,7 +273,7 @@ signed by the following secp256k1 public key 045e6c1020c14dc46442fe89f97c0b68cdb #### Coding -'Command' +_Command_ [width="80%"] |====================================================================== @@ -276,7 +281,7 @@ signed by the following secp256k1 public key 045e6c1020c14dc46442fe89f97c0b68cdb | E0 | 0A | 00 | 00 | variable | 00 |====================================================================== -'Input data' +_Input data_ [width="80%"] |======================================================================= @@ -289,7 +294,7 @@ signed by the following secp256k1 public key 045e6c1020c14dc46442fe89f97c0b68cdb | Token information signature | variable |======================================================================= -'Output data' +_Output data_ [width="80%"] |==================================================================== @@ -314,7 +319,7 @@ last, after all the EIP712 SEND STRUCT DEFINITION & SEND STRUCT IMPLEMENTATION. #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -327,7 +332,7 @@ last, after all the EIP712 SEND STRUCT DEFINITION & SEND STRUCT IMPLEMENTATION. | variable |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -340,7 +345,7 @@ last, after all the EIP712 SEND STRUCT DEFINITION & SEND STRUCT IMPLEMENTATION. | Message hash *(only for v0)* | 32 |============================================================================================================================== -'Output data' +_Output data_ [width="80%"] |============================================================================================================================== @@ -361,7 +366,7 @@ This command has been supported since firmware version 1.6.0 #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -372,7 +377,7 @@ This command has been supported since firmware version 1.6.0 | 00 | variable | variable |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -383,7 +388,7 @@ This command has been supported since firmware version 1.6.0 | Last derivation index (big endian) | 4 |============================================================================================================================== -'Output data' +_Output data_ [width="80%"] |============================================================================================================================== @@ -404,7 +409,7 @@ This command has been supported since firmware version 1.5.0 #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -413,7 +418,7 @@ This command has been supported since firmware version 1.5.0 | 00 | variable | variable |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -421,7 +426,7 @@ This command has been supported since firmware version 1.5.0 | Withdrawal key index (big endian) | 4 |============================================================================================================================== -'Output data' +_Output data_ None @@ -444,7 +449,7 @@ signed by the following secp256k1 public key 0482bbf2f34f367b2e5bc21847b6566f21f #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -452,7 +457,7 @@ signed by the following secp256k1 public key 0482bbf2f34f367b2e5bc21847b6566f21f | E0 | 12 | 00 | 00 | variable | 00 |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -464,7 +469,7 @@ signed by the following secp256k1 public key 0482bbf2f34f367b2e5bc21847b6566f21f | signature | variable |============================================================================================================================== -'Output data' +_Output data_ None @@ -483,7 +488,7 @@ type || version || len(collectionName) || collectionName || address || chainId | #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -491,7 +496,7 @@ type || version || len(collectionName) || collectionName || address || chainId | | E0 | 14 | 00 | 00 | variable | 00 |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -508,7 +513,7 @@ type || version || len(collectionName) || collectionName || address || chainId | | Signature | variable |============================================================================================================================== -'Output data' +_Output data_ [width="80%"] |==================================================================== @@ -537,7 +542,7 @@ type || version || len(pluginName) || pluginName || address || selector || chain #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -545,7 +550,7 @@ type || version || len(pluginName) || pluginName || address || selector || chain | E0 | 16 | 00 | 00 | variable | 00 |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -563,7 +568,7 @@ type || version || len(pluginName) || pluginName || address || selector || chain | Signature | variable |============================================================================================================================== -'Output data' +_Output data_ None @@ -579,7 +584,7 @@ All data can be optionally checked on the device before being returned. #### Coding -'Command' +_Command_ [width="80%"] |============================================================================================================================== @@ -592,7 +597,7 @@ All data can be optionally checked on the device before being returned. 01 : return the shared secret | variable | variable |============================================================================================================================== -'Input data' +_Input data_ [width="80%"] |============================================================================================================================== @@ -604,7 +609,7 @@ All data can be optionally checked on the device before being returned. | Third party public key on Curve25519, if returning the shared secret | 32 |============================================================================================================================== -'Output data' +_Output data_ [width="80%"] |============================================================================================================================== @@ -1096,19 +1101,19 @@ _Input data_ ##### If P1 == first chunk [width="80%"] -|========================================== -| *Description* | *Length (byte)* -| Payload length | 2 -| TLV payload | variable -|========================================== +|==================================================================== +| *Description* | *Length (byte)* +| struct size (BE) | 2 +| link:tlv_structs.md#enum_value[ENUM_VALUE struct] | variable +|==================================================================== ##### If P1 == following chunk [width="80%"] -|========================================== -| *Description* | *Length (byte)* -| TLV payload | variable -|========================================== +|==================================================================== +| *Description* | *Length (byte)* +| link:tlv_structs.md#enum_value[ENUM_VALUE struct] | variable +|==================================================================== _Output data_ @@ -1117,6 +1122,9 @@ None ### TRANSACTION INFO +#### Description +#### Coding + _Command_ [width="80%"] @@ -1133,19 +1141,19 @@ _Input data_ ##### If P1 == first chunk [width="80%"] -|========================================== -| *Description* | *Length (byte)* -| Payload length | 2 -| TLV payload | variable -|========================================== +|================================================================================ +| *Description* | *Length (byte)* +| struct size (BE) | 2 +| link:tlv_structs.md#transaction_info[TRANSACTION_INFO struct] | variable +|================================================================================ ##### If P1 == following chunk [width="80%"] -|========================================== -| *Description* | *Length (byte)* -| TLV payload | variable -|========================================== +|================================================================================ +| *Description* | *Length (byte)* +| link:tlv_structs.md#transaction_info[TRANSACTION_INFO struct] | variable +|================================================================================ _Output data_ @@ -1154,6 +1162,9 @@ None ### TRANSACTION FIELD DESCRIPTION +#### Description +#### Coding + _Command_ [width="80%"] @@ -1170,19 +1181,63 @@ _Input data_ ##### If P1 == first chunk [width="80%"] -|========================================== -| *Description* | *Length (byte)* -| Payload length | 2 -| TLV payload | variable -|========================================== +|=========================================================== +| *Description* | *Length (byte)* +| struct size (BE) | 2 +| link:tlv_structs.md#field[FIELD struct] | variable +|=========================================================== ##### If P1 == following chunk [width="80%"] -|========================================== -| *Description* | *Length (byte)* -| TLV payload | variable -|========================================== +|=========================================================== +| *Description* | *Length (byte)* +| link:tlv_structs.md#field[FIELD struct] | variable +|=========================================================== + +_Output data_ + +None + + +### PROVIDE PROXY INFO + +#### Description + +This command provides the app with the knowledge that a contract address is a proxy to another contract on a specific chain. +This can also (optionally) be restricted to a specific function within the contract. + +#### Coding + +_Command_ + +[width="80%"] +|============================================================== +| *CLA* | *INS* | *P1* | *P2* | *LC* +| E0 | 2A | 01 : first chunk + + 00 : following chunk + | 00 | 00 +|============================================================== + +_Input data_ + +##### If P1 == first chunk + +[width="80%"] +|==================================================================== +| *Description* | *Length (byte)* +| struct size (BE) | 2 +| link:tlv_structs.md#proxy_info[PROXY_INFO struct] | variable +|==================================================================== + +##### If P1 == following chunk + +[width="80%"] +|==================================================================== +| *Description* | *Length (byte)* +| link:tlv_structs.md#proxy_info[PROXY_INFO struct] | variable +|==================================================================== _Output data_ @@ -1196,7 +1251,7 @@ None This command handles the dynamic networks configuration, allowing to access funds without needing to update the application for each new network. -This configuration must be send before any access to a network and stays valid until a new config is sent. +This configuration must be sent before any access to a network and stays valid until a new config is sent. Up to *2* different configurations can be used. The targeted slot is configured automatically to the next available one. The configuration is sent in TLV (Tag-Length-Value) mode, whereas the icon itself is send as raw bytes in dedicated chunk(s). @@ -1207,7 +1262,7 @@ For the configuration, the following tags are supported: [width="80%"] |=============================================================== | *Tag name* | *Tag value* | *Length (byte)* | *Value* -| STRUCTURE_TYPE | 0x01 | 0x01 | 0x08 (for TYPE_DYNAMIC_NETWORK) +| STRUCTURE_TYPE | 0x01 | 0x01 | 0x08 (for `TYPE_DYNAMIC_NETWORK`) | STRUCTURE_VERSION | 0x02 | 0x01 | 0x01 | BLOCKCHAIN_FAMILY | 0x51 | 0x01 | 0x01 (for Ethereum) | CHAIN_ID | 0x23 | 0x08 | (`uint64_t` value) @@ -1225,25 +1280,38 @@ _Command_ [width="80%"] |============================================================== -| *CLA* | *INS* | *P1* | *P2* | *LC* | *Le* -.3+| E0 .3+| 30 | 00 | 00 : Network configuration | variable | variable - | 01 : First chunk +| *CLA* | *INS* | *P1* | *P2* | *LC* +.2+| E0 .2+| 30 | 01 : first chunk + + 00 : following chunk + | 00 : Network configuration - 00: Next chunks | 01 : Network Icon | variable | variable - | 00 | 02 : Get Info | | + 01 : Network icon | variable + | 00 | 02 : Get info | 0 |============================================================== _Input data_ -##### If P1 == Network configuration +##### If P2 == Network configuration + +###### If P1 == first chunk [width="80%"] |========================================== | *Description* | *Length (byte)* -| TLV payload data | variable +| Payload length | 2 +| TLV payload | variable |========================================== -##### If P1 == Network Icon +###### If P1 == following chunk + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| TLV payload | variable +|========================================== + +##### If P2 == Network Icon [width="80%"] |========================================== @@ -1263,7 +1331,7 @@ _Input data_ _Output data_ -##### If P1 == Get Info +##### If P2 == Get Info [width="80%"] |========================================== @@ -1274,6 +1342,118 @@ _Output data_ | Networks chain_id | 8 |========================================== +### PROVIDE TX SIMULATION + +#### Description + +This command handles the Transaction Simulation information, allowing to evaluate and verify the risk. + +There are 2 sub-commands: + +- One command to request the Opt-In flow, to inform the user a new parameter is available +- One command to send the payload data with the simulation information + +> Notes: +> +> - The Opt-In should be sent only once + + +The Transaction Simulation information must be sent before any transaction to be verified and confirmed. +It will be displayed in the review flow only if the corresponding setting is _Enabled_. + +The information is sent in TLV (Tag-Length-Value) mode. The following tags are supported: + +[width="80%"] +|=============================================================================================== +| *Tag name* | *Tag value* | *Length (byte)* | *Value* +| STRUCTURE_TYPE | 0x01 | 0x01 | 0x09 (for `TYPE_TX_SIMULATION`) +| STRUCTURE_VERSION | 0x02 | 0x01 | 0x01 +| ADDRESS | 0x22 | 0x14 | Ethereum `From` Address +| CHAIN_ID | 0x23 | 0x08 | (`uint64_t` value) +| TX_HASH | 0x27 | 0x20 | Hash of the Tx that was simulated +| DOMAIN_HASH | 0x28 | 0x20 | _Domain Hash_ for EIP712 +| W3C_NORMALIZED_RISK | 0x80 | 0x01 | Normalized risk score of the transaction. +| W3C_NORMALIZED_CATEGORY | 0x81 | 0x01 | Main category explaining the risk score +| W3C_PROVIDER_MSG | 0x82 | variable (max 30) | Provider specific message explaining the risk score +| W3C_TINY_URL | 0x83 | variable (max 30) | URL to access the full report +| W3C_SIMULATION_TYPE | 0x84 | 0x01 | Type of simulation +| SIGNATURE | 0x15 | variable | Signature of the TLV payload data +|=============================================================================================== + +The signature is mandatory, and is computed on the full payload data, using `CX_CURVE_SECP256K1`. + +Then, the App will verify the validity of this simulation using the fields: + +- `ADDRESS` +- `CHAIN_ID` +- `TX_HASH` +- `SIMULATION_TYPE` + +If one of those fields are not correct (or don't correspond to the current TX), the check status is considered _Unknown_. + +The _Risk Score_ is normalized and interpreted like this: + +- `0`: Benign +- `1`: Warning +- `2`: Malicious + +The _Simulation Type_ is normalized and interpreted like this: + +- `0`: Transaction +- `1`: Typed Data (EIP-712) +- `2`: Personal Message (EIP-191) + +#### Coding + +_Command_ + +[width="80%"] +|============================================================== +| *CLA* | *INS* | *P1* | *P2* | *LC* | *Le* +.2+| E0 .2+| 32 | 00 : TX Simulation Payload | 01 : first chunk + + 00 : following chunk | variable | variable + | 01 : TX Simulation Opt-In | 00 | 00 | 00 +|============================================================== + +_Input data_ + +##### If P1 == TX Simulation Payload + +###### If P2 == first chunk + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| Payload length | 2 +| TLV payload | variable +|========================================== + +###### If P2 == following chunk + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| TLV payload | variable +|========================================== + +##### If P1 == TX Simulation Opt-In + +None + +_Output data_ + +##### If P1 == TX Simulation Payload + +None + +##### If P1 == TX Simulation Opt-In + +[width="80%"] +|==================================== +| *Description* | *Length* +| Web3 Check setting status | 1 +|==================================== ## Transport protocol @@ -1354,7 +1534,7 @@ Requests are encoded using the standard BLE 20 bytes MTU size The following standard Status Words are returned for all APDUs - some specific Status Words can be used for specific commands and are mentioned in the command description. -'Status Words' +_Status Words_ [width="80%"] |=============================================================================================== diff --git a/doc/gcs.md b/doc/gcs.md new file mode 100644 index 0000000000..58be857420 --- /dev/null +++ b/doc/gcs.md @@ -0,0 +1,23 @@ +# Generic Clear-Signing + +```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 + HW ->> SW: OK / KO + loop N times for N fields + SW ->> HW: token / NFT / enum / trusted name metadatas + HW ->> SW: OK / KO + SW ->> HW: TX FIELD DESCRIPTION + HW ->> SW: OK / KO + end + 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 new file mode 100644 index 0000000000..d436aabe84 --- /dev/null +++ b/doc/tlv_structs.md @@ -0,0 +1,314 @@ +# TLV structures + +## TRANSACTION_INFO + +| Name | Tag | Payload type | Description | Optional | Source / value | +|--------------------|------|--------------|------------------------------------------------------|----------|------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| CHAIN_ID | 0x01 | uint64 | EIP-155 chain ID | | `$.context.contract.deployments.[].chainId` | +| CONTRACT_ADDR | 0x02 | uint8[20] | EVM contract address | | `$.context.contract.deployments.[].address` | +| SELECTOR | 0x03 | uint8[4] | selector (4 bytes form) | | `$.display.formats.` | +| FIELDS_HASH | 0x04 | uint8[32] | SHA3-256 hash of all the FIELD structs | | computed by CAL | +| OPERATION_TYPE | 0x05 | char[] | Will be appended to "Review ..." in the first screen | | `$.display.formats..intent` | +| CREATOR_NAME | 0x06 | char[] | | x | `$.metadata.owner` | +| CREATOR_LEGAL_NAME | 0x07 | char[] | | x | `$.metadata.info.legalName` | +| CREATOR_URL | 0x08 | char[] | website of the dApp or company behind it | x | `$.metadata.info.url` | +| CONTRACT_NAME | 0x09 | char[] | | x | `$.metadata.info.$id` | +| DEPLOY_DATE | 0x0a | uint32 | unix epoch, shown as YYYY-MM-DD | x | `$.metadata.info.lastUpdate` | +| SIGNATURE | 0xff | uint8[] | signature of all the other struct fields | | computed by CAL | + +> [!CAUTION] +> - `$.metadata.owner` is optional, made `CREATOR_NAME` optional +> - `$.metadata.info.legalName` is optional, made `CREATOR_LEGAL_NAME` optional +> - `$.display.formats..intent` is optional, possible fallbacks: `$.display.formats..$id`, `$.display.formats.` +> - `CONTRACT_NAME` is not really materialized in the spec, closest is `$.metadata.info.$id`, but `$id` is supposed to be internal +> - `$.metadata.info.lastUpdate` is optional, made `DEPLOY_DATE` optional + +## ENUM_VALUE + +| Name | Tag | Payload type | Description | Optional | Source / value | +|---------------|------|----------------|--------------------------------------------------------------------------|----------|------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| CHAIN_ID | 0x01 | uint64 | EIP-155 chain ID | | `$.context.contract.deployments.[].chainId` | +| CONTRACT_ADDR | 0x02 | uint8[20] | EVM contract address | | `$.context.contract.deployments.[].address` | +| SELECTOR | 0x03 | uint8[4] | function selector | | | +| ID | 0x04 | uint8 | identifier of the enum (to differentiate multiple enums in one contract) | | | +| VALUE | 0x05 | uint8 | enum entry integer value | | `$.metadata.enums...value` | +| 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 +structs, which attests of the authenticity, order and completeness of all FIELD structs. + +| Name | Tag | Payload type | Description | Optional | Source / value | +|------------|------|--------------|----------------------------|----------|------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| NAME | 0x01 | char[] | field display name (ASCII) | | `$.display.formats..fields.[].label` | +| PARAM_TYPE | 0x02 | uint8 | `ParamType` | | `$.display.formats..fields.[].params` | +| PARAM | 0x03 | PARAM_* | | | `$.display.formats..fields.[].params` | + +with `ParamType` enum defined as: + +| Name | Value | +|--------------|-------| +| RAW | 0x00 | +| AMOUNT | 0x01 | +| TOKEN_AMOUNT | 0x02 | +| NFT | 0x03 | +| DATETIME | 0x04 | +| DURATION | 0x05 | +| UNIT | 0x06 | +| ENUM | 0x07 | +| TRUSTED_NAME | 0x08 | +| CALLDATA | 0x09 | + +> [!CAUTION] +> - `NAME` max length ? + +### PARAM_RAW + +| Name | Tag | Payload type | Description | Optional | Source / value | +|---------|------|--------------|-------------------------------|----------|----------------------------------------------------------| +| 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 | +|---------|------|--------------|-------------------------------|----------|----------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | + +### PARAM_TOKEN_AMOUNT + +| Name | Tag | Payload type | Description | Optional | Source / value | +|---------------------|------|--------------|-------------------------------------------|----------|----------------------------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | +| TOKEN | 0x02 | VALUE | reference to token address | x | `$.display.formats..fields.[].params.tokenPath` | +| NATIVE_CURRENCY | 0x03 | uint8[20] | address to interpret as native currency | x | `$.display.formats..fields.[].params.nativeCurrencyAddress` | +| THRESHOLD | 0x04 | uint256 | unlimited amount threshold | x | `$.display.formats..fields.[].params.threshold` | | +| ABOVE_THRESHOLD_MSG | 0x05 | char[] | unlimited amount label | x | `$.display.formats..fields.[].params.message` | | + +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 | +|------------|------|--------------|-------------------------------------|----------|---------------------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | +| COLLECTION | 0x02 | VALUE | reference to the collection address | | `$.display.formats..fields.[].params.collectionPath` | + +### PARAM_DATETIME + +| Name | Tag | Payload type | Description | Optional | Source / value | +|---------|------|--------------|-------------------------------------|----------|---------------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | +| TYPE | 0x02 | uint8 | 0 for unix time, 1 for block height | | `$.display.formats..fields.[].params.encoding` | + +### PARAM_DURATION + +| Name | Tag | Payload type | Description | Optional | Source / value | +|---------|------|--------------|-------------------------------|----------|----------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | + +### PARAM_UNIT + +| Name | Tag | Payload type | Description | Optional | Source / value | +|----------|------|--------------|-------------------------------|----------|---------------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | +| BASE | 0x02 | char[] | | | `$.display.formats..fields.[].params.base` | +| 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 | +|---------|------|--------------|-------------------------------|----------|----------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| 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 | +|----------------|------|---------------------|--------------------------------------------|----------|--------------------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | +| TYPES | 0x02 | TrustedNameType[] | allowed types for types for trusted name | | `$.display.formats..fields.[].params.types` | +| SOURCES | 0x03 | TrustedNameSource[] | allowed sources for types for trusted name | | `$.display.formats..fields.[].params.sources` | +| SENDER_ADDRESS | 0x04 | uint8[20] | address to interpret as the sender | x | `$.display.formats..fields.[].params.senderAddress` | + +This struct can contain `SENDER_ADDRESS` multiple times for multiple addresses. + +with `TrustedNameType` enum defined as: + +| Name | Value | Description | +|-----------------|-------|----------------------------------------------------------------------------------------------------| +| EOA | 0x01 | Address is an Externally Owned Account. | +| SMART_CONTRACT | 0x02 | Address is smart contract. | +| COLLECTION | 0x03 | Address is a well known NFT collection. | +| TOKEN | 0x04 | Address is a token contract. | +| WALLET | 0x05 | Address is owned by the wallet. | +| CONTEXT_ADDRESS | 0x06 | Alias address bound to a specific execution context (e.g SPL address, contract specific address…). | + +and `TrustedNameSource` enum defined as: + +| Name | Value | Description | +|--------------------|-------|--------------------| +| LOCAL_ADDRESS_BOOK | 0x00 | Local address book | +| CRYPTO_ASSET_LIST | 0x01 | CAL | +| ENS | 0x02 | ENS | +| UNSTOPPABLE_DOMAIN | 0x03 | Unstoppable Domain | +| FREENAME | 0x04 | Freename | +| DNS | 0x05 | DNS | +| DYNAMIC_RESOLVER | 0x06 | Dynamic Resolver | + + +> [!CAUTION] +> - `SOURCES` array max length ? + +### PARAM_TOKEN + +| Name | Tag | Payload type | Description | Optional | Source / value | +|-----------------|------|--------------|-----------------------------------------|----------|----------------------------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| ADDRESS | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | +| NATIVE_CURRENCY | 0x02 | uint8[20] | address to interpret as native currency | x | `$.display.formats..fields.[].params.nativeCurrencyAddress` | + +This struct can contain `NATIVE_CURRENCY` multiple times for multiple addresses. + +### VALUE + +| Name | Tag | Payload type | Description | Optional | Source / value | +|----------------|------|-----------------|-----------------------------------------|----------|-----------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| TYPE_FAMILY | 0x01 | `TypeFamily` | | | | +| TYPE_SIZE | 0x02 | uint8 | size of values (in bytes) | x | | +| DATA_PATH | 0x03 | DATA_PATH | path to value in serialized transaction | x | `$.display.formats..fields.[].path` | +| CONTAINER_PATH | 0x04 | `ContainerPath` | container value enum | x | `$.display.formats..fields.[].path` | +| CONSTANT | 0x05 | uint8[] | literal value | x | `$.display.formats..fields.[].value` | + +with `TypeFamily` enum defined as: + +| Name | Value | +|---------|-------| +| UINT | 0x01 | +| INT | 0x02 | +| UFIXED | 0x03 | +| FIXED | 0x04 | +| ADDRESS | 0x05 | +| BOOL | 0x06 | +| BYTES | 0x07 | +| STRING | 0x08 | + +and `ContainerPath` enum defined as: + +| Name | Value | +|-------|-------| +| FROM | 0x00 | +| TO | 0x01 | +| VALUE | 0x02 | + +The TLV payload must include exactly one of `DATA_PATH`, `CONTAINER_PATH` or `CONSTANT`. + +with `TypeFamily` enum defined as: + +| Name | Value | +|---------|-------| +| UINT | 0x01 | +| INT | 0x02 | +| UFIXED | 0x03 | +| FIXED | 0x04 | +| ADDRESS | 0x05 | +| BOOL | 0x06 | +| BYTES | 0x07 | +| STRING | 0x08 | + + +> [!CAUTION] +> - `PATH` max allowed length ? + +### DATA_PATH + +| Name | Tag | Payload type | Description | Optional | Source / value | +|---------|------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| TUPLE | 0x01 | uint16 | move by {value} slots from current slot | x | | +| ARRAY | 0x02 | ARRAY_ELEMENT | current slot is array length, added to offset if negative. multiple by item_size and move by result slots. payload unset => iterate array | x | | +| REF | 0x03 | | read value of current slot. apply read value as offset from current slot | x | | +| LEAF | 0x04 | `PathLeafType` | current slot is a leaf type, specifying the type of path end | x | | +| SLICE | 0x05 | SLICE_ELEMENT | specify slicing to apply to final leaf value as (start, end) | x | | + +with `PathLeafType` enum defined as: + +| Name | Value | Description | +|--------------|-------|-------------------------------------------------------------------| +| ARRAY_LEAF | 0x01 | final offset is start of array encoding | +| TUPLE_LEAF | 0x02 | final offset is start of tuple encoding | +| STATIC_LEAF | 0x03 | final offset contains static encoded value (typ data on 32 bytes) | +| DYNAMIC_LEAF | 0x04 | final offset contains dynamic encoded value (typ length + data) | + +The payload must contain exactly one of `TUPLE`, `ARRAY`, `REF`, `LEAF` or `SLICE`. + +In version 1 of the protocol: + - `ARRAY_LEAF` and `TUPLE_LEAF` are forbidden + - `ARRAY` with no payload means the same format should be applied to each array element. It can be used several + times in a single path, in which case the application will recurse into sub-arrays (depth first) + - `LEAF` can only be used in last position of the path, expect if followed by a slice + - `SLICE` can only be used when all these conditions are met: + - 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 | +|---------|------|-----------------|--------------------------------------|----------|-----------------| +| WEIGHT | 0x01 | uint8 | size of each array element in chunks | | | +| START | 0x02 | int16 | start index (inclusive) | x | | +| END | 0x03 | int16 | end index (exclusive) | x | | + +### SLICE_ELEMENT + +| Name | Tag | Payload type | Description | Optional | Source / value | +|---------|------|-----------------|--------------------------|----------|-----------------| +| START | 0x01 | int16 | start index (inclusive) | x | | +| END | 0x02 | int16 | end index (exclusive) | x | | + +## PROXY_INFO + +| Name | Tag | Payload type | Description | Optional | +|----------------|------|-----------------|---------------------------------|----------| +| STRUCT_TYPE | 0x01 | uint8 | structure type | | +| STRUCT_VERSION | 0x02 | uint8 | structure version | | +| CHALLENGE | 0x12 | uint32 | challenge to ensure freshness | | +| ADDRESS | 0x22 | uint8[20] | proxy contract address | | +| CHAIN_ID | 0x23 | uint64 | EVM chain identifier | | +| SELECTOR | 0x28 | uint[4] | function selector | x | +| IMPL_ADDRESS | 0x29 | uint8[20] | implementation contract address | | +| SIGNATURE | 0x15 | uint8[] | signature of the structure | | diff --git a/ethereum-plugin-sdk b/ethereum-plugin-sdk index e6fde734e1..99d7871a13 160000 --- a/ethereum-plugin-sdk +++ b/ethereum-plugin-sdk @@ -1 +1 @@ -Subproject commit e6fde734e18010b5ec06fc31a112314f3046f5e0 +Subproject commit 99d7871a13cae92c4ca65b5bcfd9a800f8056463 diff --git a/glyphs/chain_80094_64px.gif b/glyphs/chain_80094_64px.gif new file mode 100644 index 0000000000..537ef87911 Binary files /dev/null and b/glyphs/chain_80094_64px.gif differ diff --git a/glyphs/review_info_button.gif b/glyphs/review_info_button.gif deleted file mode 100644 index 82b19e7172..0000000000 Binary files a/glyphs/review_info_button.gif and /dev/null differ diff --git a/makefile_conf/features.mk b/makefile_conf/features.mk index 615b8b2f77..a0d688b36e 100644 --- a/makefile_conf/features.mk +++ b/makefile_conf/features.mk @@ -67,6 +67,12 @@ ifneq ($(TARGET_NAME),TARGET_NANOS) DEFINES += HAVE_DYNAMIC_NETWORKS endif +# Web3 Checks +# TODO: remove this check once the web3 checks are implemented on all targets +# ifneq ($(TARGET_NAME),TARGET_NANOS) +ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX)) + DEFINES += HAVE_WEB3_CHECKS +endif # Check features incompatibilities # -------------------------------- diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000000..49fc0d8d6d --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +testpaths = tests/ragger +pythonpath = tests/ragger +addopts = tests/ragger diff --git a/src/apdu_constants.h b/src/apdu_constants.h index 22a4eda3de..173c42a8c8 100644 --- a/src/apdu_constants.h +++ b/src/apdu_constants.h @@ -6,6 +6,8 @@ #define APP_FLAG_DATA_ALLOWED 0x01 #define APP_FLAG_EXTERNAL_TOKEN_NEEDED 0x02 +#define APP_FLAG_W3C_ENABLE 0x10 +#define APP_FLAG_W3C_OPT_IN 0x20 #define CLA 0xE0 #define INS_GET_PUBLIC_KEY 0x02 @@ -28,17 +30,20 @@ #define INS_PROVIDE_ENUM_VALUE 0x24 #define INS_GTP_TRANSACTION_INFO 0x26 #define INS_GTP_FIELD 0x28 +#define INS_PROVIDE_PROXY_INFO 0x2A #define INS_PROVIDE_NETWORK_CONFIGURATION 0x30 -#define P1_CONFIRM 0x01 -#define P1_NON_CONFIRM 0x00 -#define P2_NO_CHAINCODE 0x00 -#define P2_CHAINCODE 0x01 -#define P1_FIRST 0x00 -#define P1_MORE 0x80 -#define P1_FIRST_CHUNK 0x01 -#define P1_FOLLOWING_CHUNK 0x00 -#define P2_EIP712_LEGACY_IMPLEM 0x00 -#define P2_EIP712_FULL_IMPLEM 0x01 +#define INS_PROVIDE_TX_SIMULATION 0x32 + +#define P1_CONFIRM 0x01 +#define P1_NON_CONFIRM 0x00 +#define P2_NO_CHAINCODE 0x00 +#define P2_CHAINCODE 0x01 +#define P1_FIRST 0x00 +#define P1_MORE 0x80 +#define P1_FIRST_CHUNK 0x01 +#define P1_FOLLOWING_CHUNK 0x00 +#define P2_EIP712_LEGACY_IMPLEM 0x00 +#define P2_EIP712_FULL_IMPLEM 0x01 #define APDU_NO_RESPONSE 0x0000 #define APDU_RESPONSE_MODE_CHECK_FAILED 0x6001 diff --git a/src/chainConfig.h b/src/chainConfig.h index cc0f5b8d50..b73dd6e90d 100644 --- a/src/chainConfig.h +++ b/src/chainConfig.h @@ -18,9 +18,6 @@ #ifndef _CHAIN_CONFIG_H_ #define _CHAIN_CONFIG_H_ -#include - -#include "os.h" #include "asset_info.h" typedef struct chain_config_s { diff --git a/src/common_ui.h b/src/common_ui.h index 06ffc5d106..18cd49a346 100644 --- a/src/common_ui.h +++ b/src/common_ui.h @@ -1,9 +1,8 @@ #ifndef _COMMON_UI_H_ #define _COMMON_UI_H_ -#include #include -#include "ui_logic.h" +#include void ui_idle(void); void ui_warning_blind_signing(void); @@ -32,7 +31,4 @@ void ui_712_switch_to_sign(void); // Generic clear-signing bool ui_gcs(void); -#include "ui_callbacks.h" -#include - #endif // _COMMON_UI_H_ diff --git a/src/eth_plugin_handler.c b/src/eth_plugin_handler.c index 2a02535105..2924ea1883 100644 --- a/src/eth_plugin_handler.c +++ b/src/eth_plugin_handler.c @@ -272,6 +272,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { os_lib_call(params); } CATCH_OTHER(e) { + (void) e; PRINTF("Plugin call exception for %s\n", alias); } FINALLY { diff --git a/src/handle_check_address.c b/src/handle_check_address.c index cf9e4f9c6d..0fc7905243 100644 --- a/src/handle_check_address.c +++ b/src/handle_check_address.c @@ -1,8 +1,5 @@ #include "handle_check_address.h" #include "apdu_constants.h" -#include "os.h" -#include "shared_context.h" -#include "string.h" #include "crypto_helpers.h" #define ZERO(x) explicit_bzero(&x, sizeof(x)) diff --git a/src/handle_get_printable_amount.c b/src/handle_get_printable_amount.c index 5b8d1f6c00..ca299869c6 100644 --- a/src/handle_get_printable_amount.c +++ b/src/handle_get_printable_amount.c @@ -1,12 +1,5 @@ -#include -#include - +#include "os.h" #include "eth_swap_utils.h" -#include "handle_get_printable_amount.h" -#include "shared_context.h" -#include "common_utils.h" -#include "uint256.h" -#include "string.h" #include "network.h" #include "apdu_constants.h" diff --git a/src/handle_swap_sign_transaction.c b/src/handle_swap_sign_transaction.c index 8faecbb9f0..e3dff7f7ad 100644 --- a/src/handle_swap_sign_transaction.c +++ b/src/handle_swap_sign_transaction.c @@ -1,25 +1,11 @@ -#include "os_io_seproxyhal.h" -#include "os.h" -#include "ux.h" #include "eth_swap_utils.h" -#include "handle_swap_sign_transaction.h" #include "shared_context.h" -#include "common_utils.h" #include "network.h" #include "cmd_setPlugin.h" #ifdef HAVE_NBGL #include "nbgl_use_case.h" #endif // HAVE_NBGL -// Remember if we have been started by the Exchange application or not -bool G_called_from_swap; - -// Set this boolean when a transaction is signed in Swap mode. Safety against double sign -bool G_swap_response_ready; - -// Save the BSS address where we will write the return value when finished -static uint8_t* G_swap_sign_return_value_address; - // Standard or crosschain swap type swap_mode_t G_swap_mode; @@ -144,7 +130,7 @@ bool copy_transaction_parameters(create_transaction_parameters_t* sign_transacti // Full reset the global variables os_explicit_zero_BSS_segment(); // Keep the address at which we'll reply the signing status - G_swap_sign_return_value_address = &sign_transaction_params->result; + G_swap_signing_return_value_address = &sign_transaction_params->result; // Commit the values read from exchange to the clean global space G_swap_mode = swap_mode; memcpy(G_swap_crosschain_hash, swap_crosschain_hash, sizeof(G_swap_crosschain_hash)); @@ -152,8 +138,8 @@ bool copy_transaction_parameters(create_transaction_parameters_t* sign_transacti return true; } -void __attribute__((noreturn)) finalize_exchange_sign_transaction(bool is_success) { - *G_swap_sign_return_value_address = is_success; +void __attribute__((noreturn)) swap_finalize_exchange_sign_transaction(bool is_success) { + *G_swap_signing_return_value_address = is_success; os_lib_end(); } @@ -171,7 +157,7 @@ void __attribute__((noreturn)) handle_swap_sign_transaction(const chain_config_t storage_init(); -#ifdef HAVE_NBGL +#ifdef SCREEN_SIZE_WALLET nbgl_useCaseSpinner("Signing"); #endif // HAVE_NBGL diff --git a/src/handle_swap_sign_transaction.h b/src/handle_swap_sign_transaction.h index 1b5d877f23..ebf911c877 100644 --- a/src/handle_swap_sign_transaction.h +++ b/src/handle_swap_sign_transaction.h @@ -8,4 +8,4 @@ bool copy_transaction_parameters(create_transaction_parameters_t* sign_transacti void __attribute__((noreturn)) handle_swap_sign_transaction(const chain_config_t* config); -void __attribute__((noreturn)) finalize_exchange_sign_transaction(bool is_success); +void __attribute__((noreturn)) swap_finalize_exchange_sign_transaction(bool is_success); diff --git a/src/ledger_pki.c b/src/ledger_pki.c index 214bb42aa3..48d31cad48 100644 --- a/src/ledger_pki.c +++ b/src/ledger_pki.c @@ -11,6 +11,9 @@ : x == CERTIFICATE_PUBLIC_KEY_USAGE_PLUGIN_METADATA ? "PLUGIN_METADATA" \ : x == CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META ? "COIN_META" \ : x == CERTIFICATE_PUBLIC_KEY_USAGE_SEED_ID_AUTH ? "SEED_ID_AUTH" \ + : 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" \ : "Unknown") int check_signature_with_pubkey(const char *tag, diff --git a/src/main.c b/src/main.c index 3a0625f8f7..3d759444a5 100644 --- a/src/main.c +++ b/src/main.c @@ -30,18 +30,21 @@ #include "handle_swap_sign_transaction.h" #include "handle_get_printable_amount.h" #include "handle_check_address.h" +#include "swap_entrypoints.h" #include "commands_712.h" #include "challenge.h" -#include "trusted_name.h" +#include "cmd_trusted_name.h" #include "crypto_helpers.h" #include "manage_asset_info.h" -#include "network_dynamic.h" +#include "cmd_network_info.h" #ifdef HAVE_DYN_MEM_ALLOC #include "mem.h" #endif #include "cmd_enum_value.h" #include "cmd_tx_info.h" #include "cmd_field.h" +#include "cmd_get_tx_simulation.h" +#include "cmd_proxy_info.h" tmpCtx_t tmpCtx; txContext_t txContext; @@ -234,7 +237,7 @@ static uint16_t handleApdu(command_t *cmd, uint32_t *flags, uint32_t *tx) { break; case INS_ENS_PROVIDE_INFO: - sw = handle_provide_trusted_name(cmd->p1, cmd->data, cmd->lc); + sw = handle_trusted_name(cmd->p1, cmd->data, cmd->lc); break; #endif // HAVE_TRUSTED_NAME @@ -254,12 +257,24 @@ static uint16_t handleApdu(command_t *cmd, uint32_t *flags, uint32_t *tx) { break; #endif // HAVE_GENERIC_TX_PARSER +#if defined(HAVE_EIP712_FULL_SUPPORT) || defined(HAVE_GENERIC_TX_PARSER) + case INS_PROVIDE_PROXY_INFO: + sw = handle_proxy_info(cmd->p1, cmd->p2, cmd->lc, cmd->data); + break; +#endif + #ifdef HAVE_DYNAMIC_NETWORKS case INS_PROVIDE_NETWORK_CONFIGURATION: - sw = handleNetworkConfiguration(cmd->p1, cmd->p2, cmd->data, cmd->lc, tx); + sw = handle_network_info(cmd->p1, cmd->p2, cmd->data, cmd->lc, tx); break; #endif // HAVE_DYNAMIC_NETWORKS +#ifdef HAVE_WEB3_CHECKS + case INS_PROVIDE_TX_SIMULATION: + sw = handle_tx_simulation(cmd->p1, cmd->p2, cmd->data, cmd->lc, flags); + break; +#endif + default: sw = APDU_RESPONSE_INVALID_INS; break; @@ -341,7 +356,7 @@ void app_main(void) { if (io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx) == 0) { // In case of success, the apdu is sent immediately and eth exits // Reaching this code means we encountered an error - finalize_exchange_sign_transaction(false); + swap_finalize_exchange_sign_transaction(false); } else { PRINTF("Unrecoverable\n"); app_exit(); diff --git a/src/manage_asset_info.c b/src/manage_asset_info.c index 5965b5f64b..4599d07aee 100644 --- a/src/manage_asset_info.c +++ b/src/manage_asset_info.c @@ -1,5 +1,4 @@ #include "manage_asset_info.h" -#include "shared_context.h" void forget_known_assets(void) { memset(tmpCtx.transactionContext.assetSet, false, MAX_ASSETS); diff --git a/src/manage_asset_info.h b/src/manage_asset_info.h index 3b8a306136..4a3465317c 100644 --- a/src/manage_asset_info.h +++ b/src/manage_asset_info.h @@ -2,8 +2,6 @@ #define MANAGE_ASSET_INFO_H_ #include "shared_context.h" -#include "common_utils.h" -#include "asset_info.h" void forget_known_assets(void); int get_asset_index_by_addr(const uint8_t *addr); diff --git a/src/mem.c b/src/mem.c index cefdb60be5..cf105069d4 100644 --- a/src/mem.c +++ b/src/mem.c @@ -15,13 +15,15 @@ #define SIZE_MEM_BUFFER 10240 static uint8_t mem_buffer[SIZE_MEM_BUFFER]; -static size_t mem_idx; +static uint16_t mem_idx; +static uint16_t mem_rev_idx; /** * Initializes the memory buffer index */ void mem_init(void) { mem_idx = 0; + mem_rev_idx = 0; } /** @@ -41,8 +43,16 @@ void mem_reset(void) { * @return Allocated memory pointer; \ref NULL if not enough space left. */ void *mem_alloc(size_t size) { + size_t new_idx; + size_t free_size; + + if (__builtin_add_overflow((size_t) mem_idx, size, &new_idx) || + __builtin_sub_overflow(sizeof(mem_buffer), (size_t) mem_rev_idx, &free_size)) { + PRINTF("Error: overflow detected!\n"); + return NULL; + } // Buffer exceeded - if ((mem_idx + size) > sizeof(mem_buffer)) { + if (new_idx > free_size) { PRINTF("Error: mem_alloc(%u) failed!\n", size); return NULL; } @@ -65,4 +75,43 @@ void mem_dealloc(size_t size) { } } +/** + * Same as \ref mem_alloc but in reverse + * + * @param[in] size Requested allocation size in bytes + * @return Allocated memory pointer; \ref NULL if not enough space left. + */ +void *mem_rev_alloc(size_t size) { + size_t free_size; + size_t new_rev_idx; + + if (__builtin_add_overflow((size_t) mem_rev_idx, size, &new_rev_idx) || + __builtin_sub_overflow(sizeof(mem_buffer), new_rev_idx, &free_size)) { + PRINTF("Error: overflow detected!\n"); + return NULL; + } + // Buffer exceeded + if (free_size < mem_idx) { + PRINTF("Error: mem_rev_alloc(%u) failed!\n", size); + return NULL; + } + mem_rev_idx += size; + return &mem_buffer[sizeof(mem_buffer) - mem_rev_idx]; +} + +/** + * Same as \ref mem_dealloc but in reverse + * + * @param[in] size Requested deallocation size in bytes + */ +void mem_rev_dealloc(size_t size) { + // More than is already allocated + if (size > mem_rev_idx) { + PRINTF("Warning: mem_rev_dealloc(%u) with a value larger than allocated!\n", size); + mem_rev_idx = 0; + } else { + mem_rev_idx -= size; + } +} + #endif // HAVE_DYN_MEM_ALLOC diff --git a/src/mem.h b/src/mem.h index eafa79769d..e83e252166 100644 --- a/src/mem.h +++ b/src/mem.h @@ -9,6 +9,8 @@ void mem_init(void); void mem_reset(void); void *mem_alloc(size_t size); void mem_dealloc(size_t size); +void *mem_rev_alloc(size_t size); +void mem_rev_dealloc(size_t size); #endif // HAVE_DYN_MEM_ALLOC diff --git a/src/mem_utils.c b/src/mem_utils.c index b7f58ad3d4..8bfc7617bd 100644 --- a/src/mem_utils.c +++ b/src/mem_utils.c @@ -36,6 +36,22 @@ char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const length) { return mem_ptr; } +/** + * Align memory by a given value + * + * @param[in] alignment given alignment value + * @return size of the padding required for proper alignment + */ +uint8_t mem_align(size_t alignment) { + uint8_t diff = (uintptr_t) mem_alloc(0) % alignment; + + if (diff > 0) { + diff = alignment - diff; + mem_alloc(diff); + } + return diff; +} + /** * Allocate and align, required when dealing with pointers of multi-bytes data * like structures that will be dereferenced at runtime. @@ -46,14 +62,7 @@ char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const length) { * @return pointer to the memory area, \ref NULL if the allocation failed */ void *mem_alloc_and_align(size_t size, size_t alignment) { - uint8_t align_diff = (uintptr_t) mem_alloc(0) % alignment; - - if (align_diff > 0) // alignment needed - { - if (mem_alloc(alignment - align_diff) == NULL) { - return NULL; - } - } + mem_align(alignment); return mem_alloc(size); } diff --git a/src/mem_utils.h b/src/mem_utils.h index c6440e1296..55d1ae2c3c 100644 --- a/src/mem_utils.h +++ b/src/mem_utils.h @@ -4,11 +4,11 @@ #ifdef HAVE_DYN_MEM_ALLOC #include -#include #define MEM_ALLOC_AND_ALIGN_TYPE(type) mem_alloc_and_align(sizeof(type), __alignof__(type)) char *mem_alloc_and_format_uint(uint32_t value, uint8_t *const written_chars); +uint8_t mem_align(size_t alignment); void *mem_alloc_and_align(size_t size, size_t alignment); #endif // HAVE_DYN_MEM_ALLOC diff --git a/src/network.c b/src/network.c index 70ffef78fb..994a122ea2 100644 --- a/src/network.c +++ b/src/network.c @@ -1,8 +1,7 @@ -#include #include "os_utils.h" #include "os_pic.h" #include "network.h" -#include "network_dynamic.h" +#include "network_info.h" #include "shared_context.h" #include "common_utils.h" @@ -96,6 +95,7 @@ static const network_info_t NETWORK_MAPPING[] = { {.chain_id = 62320, .name = "Celo Baklava", .ticker = "bCELO"}, {.chain_id = 62621, .name = "Multivac", .ticker = "MTV"}, {.chain_id = 73799, .name = "Volta", .ticker = "VOLTA"}, + {.chain_id = 80094, .name = "Berachain", .ticker = "BERA"}, {.chain_id = 81457, .name = "Blast", .ticker = "ETH"}, {.chain_id = 84532, .name = "Base Sepolia", .ticker = "ETH"}, {.chain_id = 153153, .name = "Odyssey Chain", .ticker = "DIONE"}, @@ -127,7 +127,9 @@ static const network_info_t *get_network_from_chain_id(const uint64_t *chain_id) // Look if the network is available for (size_t i = 0; i < MAX_DYNAMIC_NETWORKS; i++) { if (DYNAMIC_NETWORK_INFO[i].chain_id == *chain_id) { - PRINTF("[NETWORK] - Found dynamic %s\n", DYNAMIC_NETWORK_INFO[i].name); + PRINTF("[NETWORK] - Found dynamic \"%s\" in slot %u\n", + DYNAMIC_NETWORK_INFO[i].name, + i); return (const network_info_t *) &DYNAMIC_NETWORK_INFO[i]; } } diff --git a/src/network.h b/src/network.h index 6310074bc5..5dfb62bfcc 100644 --- a/src/network.h +++ b/src/network.h @@ -10,8 +10,8 @@ #define MAX_NETWORK_LEN 32 // 31 characters + '\0' typedef struct network_info_s { - const char name[MAX_NETWORK_LEN]; - const char ticker[MAX_TICKER_LEN]; + char name[MAX_NETWORK_LEN]; + char ticker[MAX_TICKER_LEN]; uint64_t chain_id; #ifdef HAVE_NBGL nbgl_icon_details_t icon; diff --git a/src/shared_context.h b/src/shared_context.h index d329d043f0..32613dee4e 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -1,20 +1,10 @@ #ifndef _SHARED_CONTEXT_H_ #define _SHARED_CONTEXT_H_ -#include -#include - -#include "os.h" -#include "cx.h" -#include "bip32.h" #include "bip32_utils.h" #include "ethUstream.h" -#include "tx_content.h" #include "chainConfig.h" -#include "asset_info.h" -#ifdef HAVE_NBGL -#include "nbgl_types.h" -#endif +#include "swap_utils.h" extern void app_exit(void); extern void common_app_init(void); @@ -37,6 +27,11 @@ typedef struct internalStorage_t { #ifdef HAVE_TRUSTED_NAME bool verbose_trusted_name; #endif // HAVE_TRUSTED_NAME +#ifdef HAVE_WEB3_CHECKS + bool w3c_enable; + // hidden setting (not shown in the UI) + bool w3c_opt_in; +#endif bool initialized; } internalStorage_t; @@ -113,7 +108,12 @@ typedef union { tokenContext_t tokenContext; } dataContext_t; -typedef enum { APP_STATE_IDLE, APP_STATE_SIGNING_TX, APP_STATE_SIGNING_MESSAGE } app_state_t; +typedef enum { + APP_STATE_IDLE, + APP_STATE_SIGNING_TX, + APP_STATE_SIGNING_MESSAGE, + APP_STATE_SIGNING_EIP712 +} app_state_t; typedef enum { CONTRACT_NONE, @@ -172,8 +172,6 @@ typedef enum swap_mode_e { SWAP_MODE_ERROR, } swap_mode_t; -extern bool G_called_from_swap; -extern bool G_swap_response_ready; extern swap_mode_t G_swap_mode; extern uint8_t G_swap_crosschain_hash[CX_SHA256_SIZE]; diff --git a/src/signature.h b/src/signature.h new file mode 100644 index 0000000000..e4cabc6531 --- /dev/null +++ b/src/signature.h @@ -0,0 +1,6 @@ +#ifndef SIGNATURE_H_ +#define SIGNATURE_H_ + +#define ECDSA_SIGNATURE_MAX_LENGTH 73 + +#endif // SIGNATURE_H_ diff --git a/src/tlv.c b/src/tlv.c index 7cc1cca878..7ec273f243 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -3,6 +3,7 @@ #include "tlv.h" #include "os_print.h" // PRINTF #include "read.h" // read_u32_be +#include "utils.h" // buf_shrink_expand typedef enum { TLV_STATE_TAG, TLV_STATE_LENGTH, TLV_STATE_VALUE } e_tlv_state; @@ -30,8 +31,7 @@ static bool parse_der_value(const uint8_t *payload, PRINTF("Unexpectedly long DER-encoded value (%u bytes)\n", byte_length); return false; } - memset(buf, 0, (sizeof(buf) - byte_length)); - memcpy(buf + (sizeof(buf) - byte_length), &payload[*offset], byte_length); + buf_shrink_expand(&payload[*offset], byte_length, buf, sizeof(buf)); *value = read_u32_be(buf, 0); *offset += byte_length; } else { // short form diff --git a/src/tlv_apdu.c b/src/tlv_apdu.c index a8bc02f76d..811c9ec3c6 100644 --- a/src/tlv_apdu.c +++ b/src/tlv_apdu.c @@ -8,9 +8,19 @@ #ifdef HAVE_DYN_MEM_ALLOC static uint8_t *g_tlv_payload = NULL; -static uint16_t g_tlv_size; -static uint16_t g_tlv_pos; -static bool g_dyn; +static uint16_t g_tlv_size = 0; +static uint16_t g_tlv_pos = 0; +static bool g_dyn = false; + +static void reset_state(void) { + if (g_tlv_payload != NULL) { + mem_dealloc(g_tlv_size); + } + g_tlv_payload = NULL; + g_tlv_size = 0; + g_tlv_pos = 0; + g_dyn = false; +} #endif bool tlv_from_apdu(bool first_chunk, @@ -36,8 +46,7 @@ bool tlv_from_apdu(bool first_chunk, #ifdef HAVE_DYN_MEM_ALLOC if (g_tlv_payload != NULL) { PRINTF("Error: remnants from an incomplete TLV payload!\n"); - mem_dealloc(g_tlv_size); - g_tlv_payload = NULL; + reset_state(); return false; } @@ -55,6 +64,7 @@ bool tlv_from_apdu(bool first_chunk, } #ifdef HAVE_DYN_MEM_ALLOC if (g_dyn && (g_tlv_payload == NULL)) { + reset_state(); return false; } #endif @@ -62,10 +72,7 @@ bool tlv_from_apdu(bool first_chunk, if ((g_tlv_pos + chunk_length) > g_tlv_size) { PRINTF("TLV payload bigger than expected!\n"); #ifdef HAVE_DYN_MEM_ALLOC - if (g_dyn) { - mem_dealloc(g_tlv_size); - g_tlv_payload = NULL; - } + reset_state(); #endif return false; } @@ -81,7 +88,7 @@ bool tlv_from_apdu(bool first_chunk, if (g_tlv_pos == g_tlv_size) { #ifdef HAVE_DYN_MEM_ALLOC ret = (*handler)(g_dyn ? g_tlv_payload : &payload[offset], g_tlv_size, g_dyn); - g_tlv_payload = NULL; + reset_state(); #else ret = (*handler)(&payload[offset], g_tlv_size, false); #endif diff --git a/src/ui_callbacks.h b/src/ui_callbacks.h index 52296356fe..d46c3790a3 100644 --- a/src/ui_callbacks.h +++ b/src/ui_callbacks.h @@ -3,10 +3,6 @@ #include "shared_context.h" #include "ux.h" -#ifdef HAVE_NBGL -typedef int bagl_element_t; -#endif - unsigned int io_seproxyhal_touch_tx_ok(void); unsigned int io_seproxyhal_touch_tx_cancel(void); unsigned int io_seproxyhal_touch_address_ok(void); diff --git a/src/utils.c b/src/utils.c index 012f351ff2..ab39c8ec3d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,3 +1,4 @@ +#include #include #include "utils.h" @@ -29,3 +30,20 @@ void str_cpy_explicit_trunc(const char *src, size_t src_size, char *dst, size_t memcpy(&dst[off], trunc_marker, sizeof(trunc_marker)); } } + +/** + * @brief Check the name is printable. + * + * @param[in] data buffer received + * @param[in] name Name to check + * @param[in] len Length of the name + * @return True/False + */ +bool check_name(const uint8_t *name, uint16_t len) { + for (uint16_t i = 0; i < len; i++) { + if (!isprint(name[i])) { + return false; + } + } + return true; +} diff --git a/src/utils.h b/src/utils.h index 20e2c99b21..a0f48f726b 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,10 +2,12 @@ #define UTILS_H_ #include +#include #define SET_BIT(a) (1 << a) void buf_shrink_expand(const uint8_t *src, size_t src_size, uint8_t *dst, size_t dst_size); void str_cpy_explicit_trunc(const char *src, size_t src_size, char *dst, size_t dst_size); +bool check_name(const uint8_t *name, uint16_t len); #endif // !UTILS_H_ diff --git a/src_bagl/common_ui.c b/src_bagl/common_ui.c index 96826f8e68..3aef4442e8 100644 --- a/src_bagl/common_ui.c +++ b/src_bagl/common_ui.c @@ -3,6 +3,7 @@ #include "common_ui.h" #include "ux.h" #include "ui_flow.h" +#include "ui_callbacks.h" void ui_idle(void) { // reserve a display stack slot if none yet diff --git a/src_features/generic_tx_parser/calldata.c b/src_features/generic_tx_parser/calldata.c index 0b152f70f6..ce96ae2a71 100644 --- a/src_features/generic_tx_parser/calldata.c +++ b/src_features/generic_tx_parser/calldata.c @@ -1,46 +1,190 @@ #ifdef HAVE_GENERIC_TX_PARSER #include +#include "os_math.h" // MIN #include "calldata.h" #include "os_print.h" #include "mem.h" +#include "mem_utils.h" typedef struct { - uint8_t *ptr; - size_t size; + uint8_t selector[CALLDATA_SELECTOR_SIZE]; + // chunk_info (8 bit): + // ........ + // ^^^^^^ byte size + // ^ unused + // ^ strip direction : 0 LEFT, 1 RIGHT + // + // chunk_info (1) | chunk (n) | chunk info (1) | chunk (n) | ... + uint8_t *chunks; + size_t chunks_size; size_t expected_size; + size_t received_size; + uint8_t chunk[CALLDATA_CHUNK_SIZE]; + size_t chunk_size; } s_calldata; -static s_calldata g_calldata = {0}; +static s_calldata *g_calldata = NULL; +static uint8_t g_calldata_alignment; + +typedef enum { + CHUNK_STRIP_LEFT = 0, + CHUNK_STRIP_RIGHT = 1, +} e_chunk_strip_dir; + +#define CHUNK_INFO_SIZE_MASK 0x3f +#define CHUNK_INFO_SIZE_OFFSET 0 + +#define CHUNK_INFO_DIR_MASK 0x01 +#define CHUNK_INFO_DIR_OFFSET 7 + +#define CHUNK_INFO_SIZE(v) \ + ((v & (CHUNK_INFO_SIZE_MASK << CHUNK_INFO_SIZE_OFFSET)) >> CHUNK_INFO_SIZE_OFFSET) +#define CHUNK_INFO_DIR(v) \ + ((v & (CHUNK_INFO_DIR_MASK << CHUNK_INFO_DIR_OFFSET)) >> CHUNK_INFO_DIR_OFFSET) + +typedef uint8_t chunk_info_t; bool calldata_init(size_t size) { - if ((g_calldata.ptr = mem_alloc(size)) == NULL) { + if (g_calldata != NULL) { + calldata_cleanup(); + } + g_calldata_alignment = mem_align(__alignof__(*g_calldata)); + if ((g_calldata = mem_alloc(sizeof(*g_calldata))) == NULL) { return false; } - g_calldata.expected_size = size; + explicit_bzero(g_calldata, sizeof(*g_calldata)); + g_calldata->expected_size = size; + return true; +} + +static bool compress_chunk(s_calldata *calldata) { + uint8_t strip_left = 0; + uint8_t strip_right = 0; + chunk_info_t chunk_info = 0; + e_chunk_strip_dir strip_dir; + uint8_t stripped_size; + uint8_t start_idx; + uint8_t *ptr; + + for (int i = 0; (i < CALLDATA_CHUNK_SIZE) && (calldata->chunk[i] == 0x00); ++i) { + strip_left += 1; + } + for (int i = CALLDATA_CHUNK_SIZE - 1; (i >= 0) && (calldata->chunk[i] == 0x00); --i) { + strip_right += 1; + } + + if (strip_left >= strip_right) { + strip_dir = CHUNK_STRIP_LEFT; + stripped_size = CALLDATA_CHUNK_SIZE - strip_left; + start_idx = strip_left; + } else { + strip_dir = CHUNK_STRIP_RIGHT; + stripped_size = CALLDATA_CHUNK_SIZE - strip_right; + start_idx = 0; + } + chunk_info |= strip_dir << CHUNK_INFO_DIR_OFFSET; + chunk_info |= stripped_size << CHUNK_INFO_SIZE_OFFSET; + if ((ptr = mem_alloc(sizeof(chunk_info) + stripped_size)) == NULL) { + return false; + } + if (calldata->chunks == NULL) { + calldata->chunks = ptr; + } else { + if ((calldata->chunks + calldata->chunks_size) != ptr) { + // something was allocated in between two compressed chunks + return false; + } + } + calldata->chunks_size += sizeof(chunk_info) + stripped_size; + memcpy(ptr, &chunk_info, sizeof(chunk_info)); + memcpy(ptr + sizeof(chunk_info), calldata->chunk + start_idx, stripped_size); + return true; +} + +static bool decompress_chunk(s_calldata *calldata, size_t offset) { + chunk_info_t chunk_info = calldata->chunks[offset]; + const uint8_t *compressed_chunk = &calldata->chunks[offset + sizeof(chunk_info)]; + size_t diff; + + diff = CALLDATA_CHUNK_SIZE - CHUNK_INFO_SIZE(chunk_info); + if (CHUNK_INFO_DIR(chunk_info) == CHUNK_STRIP_LEFT) { + explicit_bzero(calldata->chunk, diff); + memcpy(&calldata->chunk[diff], compressed_chunk, CHUNK_INFO_SIZE(chunk_info)); + } else { + memcpy(calldata->chunk, compressed_chunk, CHUNK_INFO_SIZE(chunk_info)); + explicit_bzero(&calldata->chunk[CHUNK_INFO_SIZE(chunk_info)], diff); + } return true; } bool calldata_append(const uint8_t *buffer, size_t size) { - if ((g_calldata.size + size) > g_calldata.expected_size) { + uint8_t cpy_length; + + if (g_calldata == NULL) return false; + if ((g_calldata->received_size + size) > g_calldata->expected_size) { + calldata_cleanup(); return false; } - memcpy(&g_calldata.ptr[g_calldata.size], buffer, size); - g_calldata.size += size; + + // selector handling + if (g_calldata->chunks == NULL) { + if (size < CALLDATA_SELECTOR_SIZE) { + // somehow getting an imcomplete 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(); + 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(); + return false; + } + g_calldata->chunk_size = 0; + } + buffer += cpy_length; + size -= cpy_length; + g_calldata->received_size += cpy_length; + } + if (g_calldata->received_size == g_calldata->expected_size) { + PRINTF("calldata reduced by ~%u%% with compression (%u -> %u bytes)\n", + 100 - (100 * (CALLDATA_SELECTOR_SIZE + g_calldata->chunks_size) / + g_calldata->received_size), + g_calldata->received_size, + CALLDATA_SELECTOR_SIZE + g_calldata->chunks_size); + } return true; } void calldata_cleanup(void) { - mem_dealloc(g_calldata.size); - explicit_bzero(&g_calldata, sizeof(g_calldata)); + if (g_calldata != NULL) { + mem_dealloc(g_calldata->chunks_size); + mem_dealloc(sizeof(*g_calldata)); + g_calldata = NULL; + mem_dealloc(g_calldata_alignment); + } } static bool has_valid_calldata(const s_calldata *calldata) { - if (calldata->ptr == NULL) { + if (calldata == NULL) { PRINTF("Error: no calldata!\n"); return false; } - if (g_calldata.size != g_calldata.expected_size) { + if (calldata->received_size != calldata->expected_size) { PRINTF("Error: incomplete calldata!\n"); return false; } @@ -48,18 +192,24 @@ static bool has_valid_calldata(const s_calldata *calldata) { } const uint8_t *calldata_get_selector(void) { - if (!has_valid_calldata(&g_calldata) || (g_calldata.size < CALLDATA_SELECTOR_SIZE)) { + if (!has_valid_calldata(g_calldata)) { return NULL; } - return g_calldata.ptr; + return g_calldata->selector; } const uint8_t *calldata_get_chunk(int idx) { - if (!has_valid_calldata(&g_calldata) || - (g_calldata.size < (CALLDATA_SELECTOR_SIZE + ((size_t) idx + 1) * CALLDATA_CHUNK_SIZE))) { + size_t offset = 0; + + if (!has_valid_calldata(g_calldata) || (g_calldata->chunks == NULL)) { return NULL; } - return &g_calldata.ptr[CALLDATA_SELECTOR_SIZE + (idx * CALLDATA_CHUNK_SIZE)]; + for (int i = 0; i < idx; ++i) { + if (offset > g_calldata->chunks_size) return NULL; + offset += sizeof(chunk_info_t) + CHUNK_INFO_SIZE(g_calldata->chunks[offset]); + } + if (!decompress_chunk(g_calldata, offset)) return NULL; + return g_calldata->chunk; } #endif // HAVE_GENERIC_TX_PARSER diff --git a/src_features/generic_tx_parser/cmd_tx_info.c b/src_features/generic_tx_parser/cmd_tx_info.c index c5379523c7..23bd212ce0 100644 --- a/src_features/generic_tx_parser/cmd_tx_info.c +++ b/src_features/generic_tx_parser/cmd_tx_info.c @@ -5,6 +5,7 @@ #include "cx.h" #include "apdu_constants.h" #include "mem.h" +#include "mem_utils.h" #include "gtp_tx_info.h" #include "tlv.h" #include "tlv_apdu.h" @@ -12,6 +13,7 @@ #include "gtp_field_table.h" extern cx_sha3_t hash_ctx; +static uint8_t g_tx_info_alignment; static bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) { s_tx_info_ctx ctx = {0}; @@ -45,6 +47,7 @@ uint16_t handle_tx_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *paylo return APDU_RESPONSE_CONDITION_NOT_SATISFIED; } + g_tx_info_alignment = mem_align(__alignof__(*g_tx_info)); if ((g_tx_info = mem_alloc(sizeof(*g_tx_info))) == NULL) { return APDU_RESPONSE_INSUFFICIENT_MEMORY; } @@ -66,6 +69,7 @@ void gcs_cleanup(void) { if (g_tx_info != NULL) { mem_dealloc(sizeof(*g_tx_info)); g_tx_info = NULL; + mem_dealloc(g_tx_info_alignment); } calldata_cleanup(); } diff --git a/src_features/generic_tx_parser/gtp_data_path.c b/src_features/generic_tx_parser/gtp_data_path.c index 9749f0618c..426d9777bf 100644 --- a/src_features/generic_tx_parser/gtp_data_path.c +++ b/src_features/generic_tx_parser/gtp_data_path.c @@ -2,10 +2,12 @@ #include // memcpy / explicit_bzero #include "os_print.h" +#include "os_math.h" // MIN #include "gtp_data_path.h" #include "read.h" #include "utils.h" #include "calldata.h" +#include "mem.h" enum { TAG_VERSION = 0x00, @@ -141,6 +143,8 @@ static bool path_leaf(const s_leaf_args *leaf, s_parsed_value_collection *collection) { uint8_t buf[sizeof(uint16_t)]; const uint8_t *chunk; + uint8_t *leaf_buf; + uint8_t cpy_length; if (collection->size > MAX_VALUE_COLLECTION_SIZE) { return false; @@ -148,27 +152,38 @@ static bool path_leaf(const s_leaf_args *leaf, switch (leaf->type) { case LEAF_TYPE_STATIC: - collection->value[collection->size].length = CALLDATA_CHUNK_SIZE; + collection->value[collection->size].size = CALLDATA_CHUNK_SIZE; break; case LEAF_TYPE_DYNAMIC: if ((chunk = calldata_get_chunk(*offset)) == NULL) { return false; } - // TODO: properly handle multi-chunk dynamic values once calldata compression - // is implemented buf_shrink_expand(chunk, CALLDATA_CHUNK_SIZE, buf, sizeof(buf)); - collection->value[collection->size].length = read_u16_be(buf, 0); + collection->value[collection->size].size = read_u16_be(buf, 0); *offset += 1; break; default: return false; } - if ((chunk = calldata_get_chunk(*offset)) == NULL) { + collection->value[collection->size].length = collection->value[collection->size].size; + collection->value[collection->size].offset = 0; + if ((leaf_buf = mem_rev_alloc(collection->value[collection->size].length)) == NULL) { return false; } - collection->value[collection->size].ptr = chunk; + 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) { + return false; + } + cpy_length = + MIN(CALLDATA_CHUNK_SIZE, + collection->value[collection->size].length - (chunk_idx * CALLDATA_CHUNK_SIZE)); + memcpy(leaf_buf + (chunk_idx * CALLDATA_CHUNK_SIZE), chunk, cpy_length); + } + collection->value[collection->size].ptr = leaf_buf; collection->size += 1; return true; } @@ -200,6 +215,7 @@ static bool path_slice(const s_slice_args *slice, s_parsed_value_collection *col } collection->value[collection->size - 1].ptr += start; collection->value[collection->size - 1].length = (end - start); + collection->value[collection->size - 1].offset += start; return true; } @@ -308,4 +324,10 @@ bool data_path_get(const s_data_path *data_path, s_parsed_value_collection *coll return true; } +void data_path_cleanup(const s_parsed_value_collection *collection) { + for (int i = 0; i < collection->size; ++i) { + mem_rev_dealloc(collection->value[i].size); + } +} + #endif // HAVE_GENERIC_TX_PARSER diff --git a/src_features/generic_tx_parser/gtp_data_path.h b/src_features/generic_tx_parser/gtp_data_path.h index 47f84bc3d8..e868ddcd2e 100644 --- a/src_features/generic_tx_parser/gtp_data_path.h +++ b/src_features/generic_tx_parser/gtp_data_path.h @@ -55,6 +55,7 @@ typedef struct { } s_data_path_context; bool handle_data_path_struct(const s_tlv_data *data, s_data_path_context *context); +void data_path_cleanup(const s_parsed_value_collection *collection); bool data_path_get(const s_data_path *data_path, s_parsed_value_collection *collection); #endif // GTP_DATA_PATH_H_ diff --git a/src_features/generic_tx_parser/gtp_field.c b/src_features/generic_tx_parser/gtp_field.c index 9bec0c2f89..4e3e35fd1e 100644 --- a/src_features/generic_tx_parser/gtp_field.c +++ b/src_features/generic_tx_parser/gtp_field.c @@ -35,6 +35,7 @@ typedef union { #ifdef HAVE_TRUSTED_NAME s_param_trusted_name_context trusted_name_ctx; #endif + s_param_token_context token_ctx; } u_param_context; static bool handle_version(const s_tlv_data *data, s_field_ctx *context) { @@ -80,6 +81,7 @@ static bool handle_param_type(const s_tlv_data *data, s_field_ctx *context) { #ifdef HAVE_TRUSTED_NAME case PARAM_TYPE_TRUSTED_NAME: #endif + case PARAM_TYPE_TOKEN: break; default: PRINTF("Error: Unsupported param type (%u)\n", context->field->param_type); @@ -144,6 +146,10 @@ static bool handle_param(const s_tlv_data *data, s_field_ctx *context) { param_ctx.trusted_name_ctx.param = &context->field->param_trusted_name; break; #endif + case PARAM_TYPE_TOKEN: + handler = (f_tlv_data_handler) &handle_param_token_struct; + param_ctx.token_ctx.param = &context->field->param_token; + break; default: return false; } @@ -238,6 +244,9 @@ bool format_field(const s_field *field) { ret = format_param_trusted_name(&field->param_trusted_name, field->name); break; #endif + case PARAM_TYPE_TOKEN: + ret = format_param_token(&field->param_token, field->name); + break; default: ret = false; } diff --git a/src_features/generic_tx_parser/gtp_field.h b/src_features/generic_tx_parser/gtp_field.h index 2a5002f649..235f1143f9 100644 --- a/src_features/generic_tx_parser/gtp_field.h +++ b/src_features/generic_tx_parser/gtp_field.h @@ -13,6 +13,7 @@ #include "gtp_param_unit.h" #include "gtp_param_enum.h" #include "gtp_param_trusted_name.h" +#include "gtp_param_token.h" typedef enum { PARAM_TYPE_RAW = 0, @@ -24,6 +25,8 @@ typedef enum { PARAM_TYPE_UNIT, PARAM_TYPE_ENUM, PARAM_TYPE_TRUSTED_NAME, + PARAM_TYPE_CALLDATA, + PARAM_TYPE_TOKEN, } e_param_type; typedef struct { @@ -46,6 +49,7 @@ typedef struct { #ifdef HAVE_TRUSTED_NAME s_param_trusted_name param_trusted_name; #endif + 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 39569710a2..f3fe7447b7 100644 --- a/src_features/generic_tx_parser/gtp_field_table.c +++ b/src_features/generic_tx_parser/gtp_field_table.c @@ -61,13 +61,15 @@ void field_table_cleanup(void) { bool add_to_field_table(e_param_type type, const char *key, const char *value) { int offset = 0; uint8_t *ptr; - uint8_t key_len = strlen(key) + 1; - uint16_t value_len = strlen(value) + 1; + uint8_t key_len; + uint16_t value_len; if ((key == NULL) || (value == NULL)) { PRINTF("Error: NULL key/value!\n"); return false; } + key_len = strlen(key) + 1; + value_len = strlen(value) + 1; PRINTF(">>> \"%s\": \"%s\"\n", key, value); if ((ptr = mem_alloc(sizeof(type) + sizeof(uint8_t) + sizeof(uint16_t) + key_len + value_len)) == NULL) { diff --git a/src_features/generic_tx_parser/gtp_param_amount.c b/src_features/generic_tx_parser/gtp_param_amount.c index a7de6918ff..25c7dc5fd4 100644 --- a/src_features/generic_tx_parser/gtp_param_amount.c +++ b/src_features/generic_tx_parser/gtp_param_amount.c @@ -45,31 +45,32 @@ bool handle_param_amount_struct(const s_tlv_data *data, s_param_amount_context * } bool format_param_amount(const s_param_amount *param, const char *name) { + bool ret; uint64_t chain_id; const char *ticker; - s_parsed_value_collection collec; + s_parsed_value_collection collec = {0}; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); - if (!value_get(¶m->value, &collec)) { - return false; - } - chain_id = get_tx_chain_id(); - ticker = get_displayable_ticker(&chain_id, chainConfig); - for (int i = 0; i < collec.size; ++i) { - if (!amountToString(collec.value[i].ptr, - collec.value[i].length, - WEI_TO_ETHER, - ticker, - buf, - buf_size)) { - return false; - } - if (!add_to_field_table(PARAM_TYPE_AMOUNT, name, buf)) { - return false; + if ((ret = value_get(¶m->value, &collec))) { + chain_id = get_tx_chain_id(); + ticker = get_displayable_ticker(&chain_id, chainConfig); + for (int i = 0; i < collec.size; ++i) { + if (!(ret = amountToString(collec.value[i].ptr, + collec.value[i].length, + WEI_TO_ETHER, + ticker, + buf, + buf_size))) { + break; + } + if (!(ret = add_to_field_table(PARAM_TYPE_AMOUNT, name, buf))) { + break; + } } } - return true; + value_cleanup(¶m->value, &collec); + return ret; } #endif // HAVE_GENERIC_TX_PARSER diff --git a/src_features/generic_tx_parser/gtp_param_datetime.c b/src_features/generic_tx_parser/gtp_param_datetime.c index 2242aded10..e579408572 100644 --- a/src_features/generic_tx_parser/gtp_param_datetime.c +++ b/src_features/generic_tx_parser/gtp_param_datetime.c @@ -65,40 +65,38 @@ bool handle_param_datetime_struct(const s_tlv_data *data, s_param_datetime_conte } bool format_param_datetime(const s_param_datetime *param, const char *name) { - s_parsed_value_collection collec; + bool ret; + s_parsed_value_collection collec = {0}; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); uint8_t time_buf[sizeof(uint32_t)] = {0}; time_t timestamp; uint256_t block_height; - if (!value_get(¶m->value, &collec)) { - return false; - } - for (int i = 0; i < collec.size; ++i) { - switch (param->type) { - case DT_UNIX: + if ((ret = value_get(¶m->value, &collec))) { + for (int i = 0; i < collec.size; ++i) { + if (param->type == DT_UNIX) { buf_shrink_expand(collec.value[i].ptr, collec.value[i].length, time_buf, sizeof(time_buf)); timestamp = read_u32_be(time_buf, 0); - if (!time_format_to_utc(×tamp, buf, buf_size)) { - return false; + if (!(ret = time_format_to_utc(×tamp, buf, buf_size))) { + break; } - break; - case DT_BLOCKHEIGHT: + } else if (param->type == DT_BLOCKHEIGHT) { convertUint256BE(collec.value[i].ptr, collec.value[i].length, &block_height); - if (!tostring256(&block_height, 10, buf, buf_size)) { - return false; + if (!(ret = tostring256(&block_height, 10, buf, buf_size))) { + break; } + } + if (!(ret = add_to_field_table(PARAM_TYPE_DATETIME, name, buf))) { break; - } - if (!add_to_field_table(PARAM_TYPE_DATETIME, name, buf)) { - return false; + } } } - return true; + value_cleanup(¶m->value, &collec); + return ret; } #endif // HAVE_GENERIC_TX_PARSER diff --git a/src_features/generic_tx_parser/gtp_param_duration.c b/src_features/generic_tx_parser/gtp_param_duration.c index 01eae53a51..6e0149c7fc 100644 --- a/src_features/generic_tx_parser/gtp_param_duration.c +++ b/src_features/generic_tx_parser/gtp_param_duration.c @@ -52,7 +52,8 @@ bool handle_param_duration_struct(const s_tlv_data *data, s_param_duration_conte } bool format_param_duration(const s_param_duration *param, const char *name) { - s_parsed_value_collection collec; + bool ret = true; + s_parsed_value_collection collec = {0}; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); uint16_t days; @@ -63,45 +64,48 @@ bool format_param_duration(const s_param_duration *param, const char *name) { uint8_t raw_buf[sizeof(remaining)] = {0}; int off; - if (!value_get(¶m->value, &collec)) { - return false; - } - for (int i = 0; i < collec.size; ++i) { - off = 0; - buf_shrink_expand(collec.value[i].ptr, collec.value[i].length, raw_buf, sizeof(raw_buf)); - remaining = read_u64_be(raw_buf, 0); - - days = remaining / SECONDS_IN_DAY; - if (days > 0) { - snprintf(&buf[off], buf_size - off, "%dd", days); - off = strlen(buf); - } - remaining %= SECONDS_IN_DAY; - - hours = remaining / SECONDS_IN_HOUR; - if (hours > 0) { - snprintf(&buf[off], buf_size - off, "%02dh", hours); - off = strlen(buf); - } - remaining %= SECONDS_IN_HOUR; - - minutes = remaining / SECONDS_IN_MINUTE; - if (minutes > 0) { - snprintf(&buf[off], buf_size - off, "%02dm", minutes); - off = strlen(buf); - } - remaining %= SECONDS_IN_MINUTE; - - seconds = (uint8_t) remaining; - if ((seconds > 0) || (off == 0)) { - snprintf(&buf[off], buf_size - off, "%02ds", seconds); - } - - if (!add_to_field_table(PARAM_TYPE_DURATION, name, buf)) { - return false; + if ((ret = value_get(¶m->value, &collec))) { + for (int i = 0; i < collec.size; ++i) { + off = 0; + buf_shrink_expand(collec.value[i].ptr, + collec.value[i].length, + raw_buf, + sizeof(raw_buf)); + remaining = read_u64_be(raw_buf, 0); + + days = remaining / SECONDS_IN_DAY; + if (days > 0) { + snprintf(&buf[off], buf_size - off, "%dd", days); + off = strlen(buf); + } + remaining %= SECONDS_IN_DAY; + + hours = remaining / SECONDS_IN_HOUR; + if (hours > 0) { + snprintf(&buf[off], buf_size - off, "%02dh", hours); + off = strlen(buf); + } + remaining %= SECONDS_IN_HOUR; + + minutes = remaining / SECONDS_IN_MINUTE; + if (minutes > 0) { + snprintf(&buf[off], buf_size - off, "%02dm", minutes); + off = strlen(buf); + } + remaining %= SECONDS_IN_MINUTE; + + seconds = (uint8_t) remaining; + if ((seconds > 0) || (off == 0)) { + snprintf(&buf[off], buf_size - off, "%02ds", seconds); + } + + if (!(ret = add_to_field_table(PARAM_TYPE_DURATION, name, buf))) { + break; + } } } - return true; + value_cleanup(¶m->value, &collec); + return ret; } #endif // HAVE_GENERIC_TX_PARSER diff --git a/src_features/generic_tx_parser/gtp_param_enum.c b/src_features/generic_tx_parser/gtp_param_enum.c index 15d90a2f48..e1369f7b83 100644 --- a/src_features/generic_tx_parser/gtp_param_enum.c +++ b/src_features/generic_tx_parser/gtp_param_enum.c @@ -59,32 +59,37 @@ bool handle_param_enum_struct(const s_tlv_data *data, s_param_enum_context *cont } bool format_param_enum(const s_param_enum *param, const char *name) { + bool ret; uint64_t chain_id; - s_parsed_value_collection collec; + s_parsed_value_collection collec = {0}; const char *enum_name; uint8_t value; const uint8_t *selector; - if (!value_get(¶m->value, &collec)) { - return false; - } - chain_id = get_tx_chain_id(); - for (int i = 0; i < collec.size; ++i) { - if (collec.value[i].length == 0) return false; - value = collec.value[i].ptr[collec.value[i].length - 1]; - if ((selector = calldata_get_selector()) == NULL) { - return false; - } - enum_name = get_matching_enum_name(&chain_id, - txContext.content->destination, - selector, - param->id, - value); - if (!add_to_field_table(PARAM_TYPE_ENUM, name, enum_name)) { - return false; + if ((ret = value_get(¶m->value, &collec))) { + chain_id = get_tx_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) { + ret = false; + break; + } + enum_name = get_matching_enum_name(&chain_id, + txContext.content->destination, + selector, + param->id, + value); + if (!(ret = add_to_field_table(PARAM_TYPE_ENUM, name, enum_name))) { + break; + } } } - return true; + value_cleanup(¶m->value, &collec); + return ret; } #endif // HAVE_ENUM_VALUE diff --git a/src_features/generic_tx_parser/gtp_param_nft.c b/src_features/generic_tx_parser/gtp_param_nft.c index 9a3d97b010..8122d27eee 100644 --- a/src_features/generic_tx_parser/gtp_param_nft.c +++ b/src_features/generic_tx_parser/gtp_param_nft.c @@ -53,8 +53,9 @@ bool handle_param_nft_struct(const s_tlv_data *data, s_param_nft_context *contex } bool format_param_nft(const s_param_nft *param, const char *name) { - s_parsed_value_collection collections; - s_parsed_value_collection ids; + bool ret; + s_parsed_value_collection collections = {0}; + s_parsed_value_collection ids = {0}; const extraInfo_t *asset; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); @@ -62,36 +63,43 @@ bool format_param_nft(const s_param_nft *param, const char *name) { uint8_t addr_buf[ADDRESS_LENGTH]; char tmp[80]; - if (!value_get(¶m->collection, &collections)) { - return false; - } - if (!value_get(¶m->id, &ids)) { - return false; - } - if (collections.size == 0) { - return false; - } - if ((collections.size != 1) && (collections.size != ids.size)) { - return false; - } - for (int i = 0; i < ids.size; ++i) { - collection_idx = (i >= collections.size) ? 0 : i; - buf_shrink_expand(collections.value[collection_idx].ptr, - collections.value[collection_idx].length, - addr_buf, - sizeof(addr_buf)); - if ((asset = (const extraInfo_t *) get_asset_info_by_addr(addr_buf)) == NULL) { - return false; - } - if (!uint256_to_decimal(ids.value[i].ptr, ids.value[i].length, tmp, sizeof(tmp))) { - return false; - } - snprintf(buf, buf_size, "%s #%s", asset->nft.collectionName, tmp); - if (!add_to_field_table(PARAM_TYPE_NFT, name, buf)) { - return false; + if ((ret = value_get(¶m->collection, &collections))) { + if ((ret = value_get(¶m->id, &ids))) { + if (collections.size == 0) { + ret = false; + } else { + if ((collections.size != 1) && (collections.size != ids.size)) { + ret = false; + } else { + for (int i = 0; i < ids.size; ++i) { + collection_idx = (i >= collections.size) ? 0 : i; + buf_shrink_expand(collections.value[collection_idx].ptr, + collections.value[collection_idx].length, + addr_buf, + sizeof(addr_buf)); + if ((asset = (const extraInfo_t *) get_asset_info_by_addr(addr_buf)) == + NULL) { + ret = false; + break; + } + if (!(ret = uint256_to_decimal(ids.value[i].ptr, + ids.value[i].length, + tmp, + sizeof(tmp)))) { + break; + } + snprintf(buf, buf_size, "%s #%s", asset->nft.collectionName, tmp); + if (!(ret = add_to_field_table(PARAM_TYPE_NFT, name, buf))) { + break; + } + } + } + } } } - return true; + value_cleanup(¶m->collection, &collections); + value_cleanup(¶m->id, &ids); + return ret; } #endif // HAVE_NFT_SUPPORT diff --git a/src_features/generic_tx_parser/gtp_param_raw.c b/src_features/generic_tx_parser/gtp_param_raw.c index 3003835da1..d1b11ea7f6 100644 --- a/src_features/generic_tx_parser/gtp_param_raw.c +++ b/src_features/generic_tx_parser/gtp_param_raw.c @@ -146,42 +146,42 @@ static bool format_string(const s_value *def, } bool format_param_raw(const s_param_raw *param, const char *name) { - bool ret = false; - s_parsed_value_collection collec; + bool ret; + s_parsed_value_collection collec = {0}; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); - if (!value_get(¶m->value, &collec)) { - return false; - } - for (int i = 0; i < collec.size; ++i) { - switch (param->value.type_family) { - case TF_UINT: - ret = format_uint(¶m->value, &collec.value[i], buf, buf_size); - break; - case TF_INT: - ret = format_int(¶m->value, &collec.value[i], buf, buf_size); - break; - case TF_ADDRESS: - ret = format_addr(¶m->value, &collec.value[i], buf, buf_size); - break; - case TF_BOOL: - ret = format_bool(¶m->value, &collec.value[i], buf, buf_size); - break; - case TF_BYTES: - ret = format_bytes(¶m->value, &collec.value[i], buf, buf_size); - break; - case TF_STRING: - ret = format_string(¶m->value, &collec.value[i], buf, buf_size); - break; - case TF_UFIXED: - case TF_FIXED: - default: - ret = false; + if ((ret = value_get(¶m->value, &collec))) { + for (int i = 0; i < collec.size; ++i) { + switch (param->value.type_family) { + case TF_UINT: + ret = format_uint(¶m->value, &collec.value[i], buf, buf_size); + break; + case TF_INT: + ret = format_int(¶m->value, &collec.value[i], buf, buf_size); + break; + case TF_ADDRESS: + ret = format_addr(¶m->value, &collec.value[i], buf, buf_size); + break; + case TF_BOOL: + ret = format_bool(¶m->value, &collec.value[i], buf, buf_size); + break; + case TF_BYTES: + ret = format_bytes(¶m->value, &collec.value[i], buf, buf_size); + break; + case TF_STRING: + ret = format_string(¶m->value, &collec.value[i], buf, buf_size); + break; + case TF_UFIXED: + case TF_FIXED: + default: + ret = false; + } + if (ret) ret = add_to_field_table(PARAM_TYPE_RAW, name, buf); + if (!ret) break; } - if (ret) ret = add_to_field_table(PARAM_TYPE_RAW, name, buf); - if (!ret) break; } + value_cleanup(¶m->value, &collec); return ret; } diff --git a/src_features/generic_tx_parser/gtp_param_token.c b/src_features/generic_tx_parser/gtp_param_token.c new file mode 100644 index 0000000000..5d241a50cf --- /dev/null +++ b/src_features/generic_tx_parser/gtp_param_token.c @@ -0,0 +1,103 @@ +#include +#include "gtp_param_token.h" +#include "shared_context.h" +#include "utils.h" +#include "manage_asset_info.h" +#include "network.h" +#include "gtp_field_table.h" + +enum { + TAG_VERSION = 0x00, + TAG_ADDRESS = 0x01, + TAG_NATIVE_CURRENCY = 0x02, +}; + +static bool handle_version(const s_tlv_data *data, s_param_token_context *context) { + if (data->length != sizeof(context->param->version)) { + return false; + } + context->param->version = data->value[0]; + return true; +} + +static bool handle_address(const s_tlv_data *data, s_param_token_context *context) { + s_value_context ctx = {0}; + + ctx.value = &context->param->address; + 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_native_currency(const s_tlv_data *data, s_param_token_context *context) { + if (data->length > ADDRESS_LENGTH) { + return false; + } + if (context->param->native_addr_count == MAX_NATIVE_ADDRS) { + return false; + } + memcpy(&context->param + ->native_addrs[context->param->native_addr_count][ADDRESS_LENGTH - data->length], + data->value, + data->length); + context->param->native_addr_count += 1; + return true; +} + +bool handle_param_token_struct(const s_tlv_data *data, s_param_token_context *context) { + bool ret; + + switch (data->tag) { + case TAG_VERSION: + ret = handle_version(data, context); + break; + case TAG_ADDRESS: + ret = handle_address(data, context); + break; + case TAG_NATIVE_CURRENCY: + ret = handle_native_currency(data, context); + break; + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + ret = false; + } + return ret; +} + +static bool match_native(const uint8_t *addr, const s_param_token *param) { + for (int i = 0; i < param->native_addr_count; ++i) { + if (memcmp(addr, param->native_addrs[i], ADDRESS_LENGTH) == 0) { + return true; + } + } + return false; +} + +bool format_param_token(const s_param_token *param, const char *name) { + bool ret; + s_parsed_value_collection collec = {0}; + uint8_t addr[ADDRESS_LENGTH]; + const tokenDefinition_t *token_def; + uint64_t chain_id; + const char *ticker = NULL; + + chain_id = get_tx_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)); + if (match_native(addr, param)) { + ticker = get_displayable_ticker(&chain_id, chainConfig); + } else if ((token_def = (const tokenDefinition_t *) get_asset_info_by_addr(addr))) { + ticker = token_def->ticker; + } + if (ticker == NULL) { + ret = false; + break; + } + if (!(ret = add_to_field_table(PARAM_TYPE_TOKEN, name, ticker))) { + break; + } + } + } + value_cleanup(¶m->address, &collec); + return ret; +} diff --git a/src_features/generic_tx_parser/gtp_param_token.h b/src_features/generic_tx_parser/gtp_param_token.h new file mode 100644 index 0000000000..a5fa8ff448 --- /dev/null +++ b/src_features/generic_tx_parser/gtp_param_token.h @@ -0,0 +1,26 @@ +#ifndef GTP_PARAM_TOKEN_ +#define GTP_PARAM_TOKEN_ + +#include +#include +#include "common_utils.h" +#include "gtp_value.h" +#include "tlv.h" + +#define MAX_NATIVE_ADDRS 4 + +typedef struct { + uint8_t version; + s_value address; + uint8_t native_addr_count; + uint8_t native_addrs[MAX_NATIVE_ADDRS][ADDRESS_LENGTH]; +} s_param_token; + +typedef struct { + s_param_token *param; +} s_param_token_context; + +bool handle_param_token_struct(const s_tlv_data *data, s_param_token_context *context); +bool format_param_token(const s_param_token *param, const char *name); + +#endif // !GTP_PARAM_TOKEN_ 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 b68df1b317..a6976aa403 100644 --- a/src_features/generic_tx_parser/gtp_param_token_amount.c +++ b/src_features/generic_tx_parser/gtp_param_token_amount.c @@ -113,73 +113,80 @@ static bool match_native(const uint8_t *addr, const s_param_token_amount *param) return false; } -bool format_param_token_amount(const s_param_token_amount *param, const char *name) { - s_parsed_value_collection collec_value; - s_parsed_value_collection collec_token; +static bool process_token_amount(const s_param_token_amount *param, + const char *name, + s_parsed_value *value, + s_parsed_value *token) { char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); uint8_t addr_buf[ADDRESS_LENGTH]; + uint256_t zero256 = {0}; + uint256_t val256; + const tokenDefinition_t *token_def; + uint64_t chain_id = get_tx_chain_id(); + const char *ticker = g_unknown_ticker; + uint8_t decimals = 0; - if (!value_get(¶m->value, &collec_value)) { - return false; - } if (param->has_token) { - if (!value_get(¶m->token, &collec_token)) { - return false; + buf_shrink_expand(token->ptr, token->length, addr_buf, sizeof(addr_buf)); + if (match_native(addr_buf, param)) { + ticker = get_displayable_ticker(&chain_id, chainConfig); + decimals = WEI_TO_ETHER; + } else { + if ((token_def = (const tokenDefinition_t *) get_asset_info_by_addr(addr_buf)) != + NULL) { + ticker = token_def->ticker; + decimals = token_def->decimals; + } } - if (collec_value.size != collec_token.size) { - PRINTF("Error: mismatch between counts of value & token!\n"); - return false; + } + + convertUint256BE(value->ptr, value->length, &val256); + if (!equal256(¶m->threshold, &zero256) && gte256(&val256, ¶m->threshold)) { + if (param->above_threshold_msg[0] != '\0') { + snprintf(buf, buf_size, "%s %s", param->above_threshold_msg, ticker); + } else { + snprintf(buf, buf_size, "Unlimited %s", ticker); } } else { - explicit_bzero(&collec_token, sizeof(collec_token)); + if (!amountToString(value->ptr, value->length, decimals, ticker, buf, buf_size)) { + return false; + } } - uint64_t chain_id = get_tx_chain_id(); - const char *ticker = g_unknown_ticker; - uint8_t decimals = 0; - for (int i = 0; i < collec_value.size; ++i) { + if (!add_to_field_table(PARAM_TYPE_AMOUNT, name, buf)) { + return false; + } + return true; +} + +bool format_param_token_amount(const s_param_token_amount *param, const char *name) { + bool ret; + s_parsed_value_collection collec_value = {0}; + s_parsed_value_collection collec_token = {0}; + + if ((ret = value_get(¶m->value, &collec_value))) { if (param->has_token) { - buf_shrink_expand(collec_token.value[i].ptr, - collec_token.value[i].length, - addr_buf, - sizeof(addr_buf)); - if (match_native(addr_buf, param)) { - ticker = get_displayable_ticker(&chain_id, chainConfig); - decimals = WEI_TO_ETHER; - } else { - const tokenDefinition_t *token; - if ((token = (const tokenDefinition_t *) get_asset_info_by_addr(addr_buf)) != - NULL) { - ticker = token->ticker; - decimals = token->decimals; + if ((ret = value_get(¶m->token, &collec_token))) { + if (collec_value.size != collec_token.size) { + PRINTF("Error: mismatch between counts of value & token!\n"); + ret = false; } } } - uint256_t zero256 = {0}; - uint256_t val256; - - convertUint256BE(collec_value.value[i].ptr, collec_value.value[i].length, &val256); - if (!equal256(¶m->threshold, &zero256) && gte256(&val256, ¶m->threshold)) { - if (param->above_threshold_msg[0] != '\0') { - snprintf(buf, buf_size, "%s %s", param->above_threshold_msg, ticker); - } else { - snprintf(buf, buf_size, "Unlimited %s", ticker); - } - } else { - if (!amountToString(collec_value.value[i].ptr, - collec_value.value[i].length, - decimals, - ticker, - buf, - buf_size)) { - return false; + if (ret) { + for (int i = 0; i < collec_value.size; ++i) { + if (!(ret = process_token_amount(param, + name, + &collec_value.value[i], + &collec_token.value[i]))) { + break; + } } } - if (!add_to_field_table(PARAM_TYPE_AMOUNT, name, buf)) { - return false; - } } - return true; + value_cleanup(¶m->value, &collec_value); + value_cleanup(¶m->token, &collec_token); + return ret; } #endif // HAVE_GENERIC_TX_PARSER 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 4c6c279891..80a781d9d6 100644 --- a/src_features/generic_tx_parser/gtp_param_trusted_name.c +++ b/src_features/generic_tx_parser/gtp_param_trusted_name.c @@ -7,12 +7,15 @@ #include "gtp_field_table.h" #include "utils.h" #include "shared_context.h" +#include "feature_signTx.h" // get_public_key +#include "apdu_constants.h" enum { TAG_VERSION = 0x00, TAG_VALUE = 0x01, TAG_TYPES = 0x02, TAG_SOURCES = 0x03, + TAG_SENDER_ADDR = 0x04, }; static bool handle_version(const s_tlv_data *data, s_param_trusted_name_context *context) { @@ -49,6 +52,19 @@ static bool handle_sources(const s_tlv_data *data, s_param_trusted_name_context return true; } +static bool handle_sender_addr(const s_tlv_data *data, s_param_trusted_name_context *context) { + if ((data->length > sizeof(context->param->sender_addr)) || + (context->param->sender_addr_count == ARRAYLEN(context->param->sender_addr))) { + return false; + } + buf_shrink_expand(data->value, + data->length, + context->param->sender_addr[context->param->sender_addr_count], + sizeof(context->param->sender_addr[context->param->sender_addr_count])); + context->param->sender_addr_count += 1; + return true; +} + bool handle_param_trusted_name_struct(const s_tlv_data *data, s_param_trusted_name_context *context) { bool ret; @@ -66,6 +82,9 @@ bool handle_param_trusted_name_struct(const s_tlv_data *data, case TAG_SOURCES: ret = handle_sources(data, context); break; + case TAG_SENDER_ADDR: + ret = handle_sender_addr(data, context); + break; default: PRINTF(TLV_TAG_ERROR_MSG, data->tag); ret = false; @@ -74,7 +93,8 @@ bool handle_param_trusted_name_struct(const s_tlv_data *data, } bool format_param_trusted_name(const s_param_trusted_name *param, const char *name) { - s_parsed_value_collection values; + bool ret; + s_parsed_value_collection values = {0}; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); uint64_t chain_id; @@ -82,29 +102,37 @@ bool format_param_trusted_name(const s_param_trusted_name *param, const char *na const char *tname; e_param_type param_type; - if (!value_get(¶m->value, &values)) { - return false; - } - chain_id = get_tx_chain_id(); - for (int i = 0; i < values.size; ++i) { - buf_shrink_expand(values.value[i].ptr, values.value[i].length, addr, sizeof(addr)); - if ((tname = get_trusted_name(param->type_count, - param->types, - param->source_count, - param->sources, - &chain_id, - addr)) != NULL) { - strlcpy(buf, tname, buf_size); - param_type = PARAM_TYPE_TRUSTED_NAME; - } else { - getEthDisplayableAddress(addr, buf, buf_size, chainConfig->chainId); - param_type = PARAM_TYPE_RAW; - } - if (!add_to_field_table(param_type, name, buf)) { - return false; + if ((ret = value_get(¶m->value, &values))) { + chain_id = get_tx_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 + for (uint8_t idx = 0; idx < param->sender_addr_count; ++idx) { + if (memcmp(addr, param->sender_addr[idx], ADDRESS_LENGTH) == 0) { + ret = get_public_key(addr, sizeof(addr)) == APDU_RESPONSE_OK; + break; + } + } + if (!ret) break; + if ((tname = get_trusted_name(param->type_count, + param->types, + param->source_count, + param->sources, + &chain_id, + addr)) != NULL) { + strlcpy(buf, tname, buf_size); + param_type = PARAM_TYPE_TRUSTED_NAME; + } else { + getEthDisplayableAddress(addr, buf, buf_size, chainConfig->chainId); + param_type = PARAM_TYPE_RAW; + } + if (!(ret = add_to_field_table(param_type, name, buf))) { + break; + } } } - return true; + value_cleanup(¶m->value, &values); + return ret; } #endif // HAVE_TRUSTED_NAME diff --git a/src_features/generic_tx_parser/gtp_param_trusted_name.h b/src_features/generic_tx_parser/gtp_param_trusted_name.h index 3232d7ad54..1d4523c69c 100644 --- a/src_features/generic_tx_parser/gtp_param_trusted_name.h +++ b/src_features/generic_tx_parser/gtp_param_trusted_name.h @@ -9,6 +9,8 @@ #include "gtp_value.h" #include "trusted_name.h" +#define MAX_SENDER_ADDRS 3 + typedef struct { uint8_t version; s_value value; @@ -16,6 +18,8 @@ typedef struct { e_name_type types[TN_TYPE_COUNT]; uint8_t source_count; e_name_source sources[TN_SOURCE_COUNT]; + uint8_t sender_addr_count; + uint8_t sender_addr[MAX_SENDER_ADDRS][ADDRESS_LENGTH]; } s_param_trusted_name; typedef struct { diff --git a/src_features/generic_tx_parser/gtp_param_unit.c b/src_features/generic_tx_parser/gtp_param_unit.c index af00f84cb3..bc9a913cf4 100644 --- a/src_features/generic_tx_parser/gtp_param_unit.c +++ b/src_features/generic_tx_parser/gtp_param_unit.c @@ -81,33 +81,42 @@ bool handle_param_unit_struct(const s_tlv_data *data, s_param_unit_context *cont } bool format_param_unit(const s_param_unit *param, const char *name) { - s_parsed_value_collection collec; + bool ret; + s_parsed_value_collection collec = {0}; char *buf = strings.tmp.tmp; size_t buf_size = sizeof(strings.tmp.tmp); char tmp[80]; size_t off; - if (!value_get(¶m->value, &collec)) { - return false; - } - for (int i = 0; i < collec.size; ++i) { - if (!uint256_to_decimal(collec.value[i].ptr, collec.value[i].length, tmp, sizeof(tmp))) { - return false; - } - if (!adjustDecimals(tmp, strnlen(tmp, sizeof(tmp)), buf, buf_size, param->decimals)) { - return false; - } - if (param->base[0] == '\0') { - return false; - } - off = strlen(buf); - snprintf(&buf[off], buf_size - off, " %s", param->base); + if ((ret = value_get(¶m->value, &collec))) { + for (int i = 0; i < collec.size; ++i) { + if (!(ret = uint256_to_decimal(collec.value[i].ptr, + collec.value[i].length, + tmp, + sizeof(tmp)))) { + break; + } + if (!(ret = adjustDecimals(tmp, + strnlen(tmp, sizeof(tmp)), + buf, + buf_size, + param->decimals))) { + break; + } + if (param->base[0] == '\0') { + ret = false; + break; + } + off = strlen(buf); + snprintf(&buf[off], buf_size - off, " %s", param->base); - if (!add_to_field_table(PARAM_TYPE_UNIT, name, buf)) { - return false; + if (!(ret = add_to_field_table(PARAM_TYPE_UNIT, name, buf))) { + break; + } } } - return true; + value_cleanup(¶m->value, &collec); + return ret; } #endif // HAVE_GENERIC_TX_PARSER diff --git a/src_features/generic_tx_parser/gtp_parsed_value.h b/src_features/generic_tx_parser/gtp_parsed_value.h index 2f7b4bcfc0..dd77c930cd 100644 --- a/src_features/generic_tx_parser/gtp_parsed_value.h +++ b/src_features/generic_tx_parser/gtp_parsed_value.h @@ -4,8 +4,10 @@ #include typedef struct { - uint16_t length; const uint8_t *ptr; + uint16_t size; // allocated size + uint16_t offset; // slice + uint16_t length; // slice } s_parsed_value; #define MAX_VALUE_COLLECTION_SIZE 16 diff --git a/src_features/generic_tx_parser/gtp_tx_info.c b/src_features/generic_tx_parser/gtp_tx_info.c index 39ed016ca3..0deea1d1b9 100644 --- a/src_features/generic_tx_parser/gtp_tx_info.c +++ b/src_features/generic_tx_parser/gtp_tx_info.c @@ -10,6 +10,7 @@ #include "time_format.h" #include "calldata.h" #include "public_keys.h" // LEDGER_SIGNATURE_PUBLIC_KEY +#include "proxy_info.h" enum { BIT_VERSION = 0, @@ -78,10 +79,6 @@ static bool handle_contract_addr(const s_tlv_data *data, s_tx_info_ctx *context) return false; } buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); - if (memcmp(buf, txContext.content->destination, sizeof(buf)) != 0) { - PRINTF("Error: contract address mismatch!\n"); - return false; - } memcpy(context->tx_info->contract_addr, buf, sizeof(buf)); context->set_flags |= SET_BIT(BIT_CONTRACT_ADDR); return true; @@ -245,6 +242,8 @@ 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); @@ -270,6 +269,19 @@ bool verify_tx_info_struct(const s_tx_info_ctx *context) { return false; } + tx_chain_id = get_tx_chain_id(); + if (((proxy_parent = get_proxy_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, @@ -287,8 +299,7 @@ bool verify_tx_info_struct(const s_tx_info_ctx *context) { NULL, 0, #ifdef HAVE_LEDGER_PKI - // TODO: change once SDK has the enum value for this - 0x0b, + CERTIFICATE_PUBLIC_KEY_USAGE_CALLDATA, #endif (uint8_t *) context->tx_info->signature, context->tx_info->signature_len) != CX_OK) { diff --git a/src_features/generic_tx_parser/gtp_tx_info.h b/src_features/generic_tx_parser/gtp_tx_info.h index 443cfb3746..5c4ccd0505 100644 --- a/src_features/generic_tx_parser/gtp_tx_info.h +++ b/src_features/generic_tx_parser/gtp_tx_info.h @@ -7,6 +7,7 @@ #include "common_utils.h" // ADDRESS_LENGTH, INT256_LENGTH #include "calldata.h" #include "tlv.h" +#include "signature.h" typedef struct { uint8_t version; @@ -22,7 +23,7 @@ typedef struct { // YYYY-MM-DD\0 char deploy_date[4 + 1 + 2 + 1 + 2 + 1]; uint8_t signature_len; - uint8_t signature[73]; + uint8_t signature[ECDSA_SIGNATURE_MAX_LENGTH]; } s_tx_info; typedef struct { diff --git a/src_features/generic_tx_parser/gtp_value.c b/src_features/generic_tx_parser/gtp_value.c index bc4c775cce..d1437b90d5 100644 --- a/src_features/generic_tx_parser/gtp_value.c +++ b/src_features/generic_tx_parser/gtp_value.c @@ -159,4 +159,10 @@ bool value_get(const s_value *value, s_parsed_value_collection *collection) { return ret; } +void value_cleanup(const s_value *value, const s_parsed_value_collection *collection) { + if (value->source == SOURCE_CALLDATA) { + data_path_cleanup(collection); + } +} + #endif // HAVE_GENERIC_TX_PARSER diff --git a/src_features/generic_tx_parser/gtp_value.h b/src_features/generic_tx_parser/gtp_value.h index c6a49b3767..cc817fd09c 100644 --- a/src_features/generic_tx_parser/gtp_value.h +++ b/src_features/generic_tx_parser/gtp_value.h @@ -53,5 +53,6 @@ typedef struct { bool handle_value_struct(const s_tlv_data *data, s_value_context *context); bool value_get(const s_value *value, s_parsed_value_collection *collection); +void value_cleanup(const s_value *value, const s_parsed_value_collection *collection); #endif // !GTP_VALUE_H_ diff --git a/src_features/getAppConfiguration/cmd_getAppConfiguration.c b/src_features/getAppConfiguration/cmd_getAppConfiguration.c index 761612314a..57664df48c 100644 --- a/src_features/getAppConfiguration/cmd_getAppConfiguration.c +++ b/src_features/getAppConfiguration/cmd_getAppConfiguration.c @@ -3,6 +3,10 @@ uint16_t handleGetAppConfiguration(unsigned int *tx) { G_io_apdu_buffer[0] = (N_storage.dataAllowed ? APP_FLAG_DATA_ALLOWED : 0x00); +#ifdef HAVE_WEB3_CHECKS + G_io_apdu_buffer[0] |= (N_storage.w3c_enable ? APP_FLAG_W3C_ENABLE : 0x00); + G_io_apdu_buffer[0] |= (N_storage.w3c_opt_in ? APP_FLAG_W3C_OPT_IN : 0x00); +#endif G_io_apdu_buffer[0] |= APP_FLAG_EXTERNAL_TOKEN_NEEDED; G_io_apdu_buffer[1] = MAJOR_VERSION; G_io_apdu_buffer[2] = MINOR_VERSION; diff --git a/src_features/getChallenge/cmd_get_challenge.c b/src_features/getChallenge/cmd_get_challenge.c index 84898aa2fd..83a5942d1f 100644 --- a/src_features/getChallenge/cmd_get_challenge.c +++ b/src_features/getChallenge/cmd_get_challenge.c @@ -1,8 +1,7 @@ #ifdef HAVE_TRUSTED_NAME -#include -#include -#include +#include "os_io.h" +#include "cx.h" #include "apdu_constants.h" #include "challenge.h" diff --git a/src_features/getEth2PublicKey/ui_common_getEth2PublicKey.c b/src_features/getEth2PublicKey/ui_common_getEth2PublicKey.c index 81dbea90d3..a3e668b884 100644 --- a/src_features/getEth2PublicKey/ui_common_getEth2PublicKey.c +++ b/src_features/getEth2PublicKey/ui_common_getEth2PublicKey.c @@ -1,9 +1,8 @@ #ifdef HAVE_ETH2 -#include "shared_context.h" #include "apdu_constants.h" #include "feature_getEth2PublicKey.h" -#include "common_ui.h" +#include "ui_callbacks.h" unsigned int io_seproxyhal_touch_eth2_address_ok(void) { uint32_t tx = set_result_get_eth2_publicKey(); diff --git a/src_features/getPublicKey/ui_common_getPublicKey.c b/src_features/getPublicKey/ui_common_getPublicKey.c index fe1a0bae03..abee554254 100644 --- a/src_features/getPublicKey/ui_common_getPublicKey.c +++ b/src_features/getPublicKey/ui_common_getPublicKey.c @@ -1,7 +1,6 @@ -#include "shared_context.h" #include "apdu_constants.h" #include "feature_getPublicKey.h" -#include "common_ui.h" +#include "ui_callbacks.h" unsigned int io_seproxyhal_touch_address_ok(void) { uint32_t tx = set_result_get_publicKey(); diff --git a/src_features/performPrivacyOperation/ui_common_performPrivacyOperation.c b/src_features/performPrivacyOperation/ui_common_performPrivacyOperation.c index 652e6be11b..70413b0539 100644 --- a/src_features/performPrivacyOperation/ui_common_performPrivacyOperation.c +++ b/src_features/performPrivacyOperation/ui_common_performPrivacyOperation.c @@ -1,7 +1,5 @@ -#include "shared_context.h" #include "apdu_constants.h" -#include "feature_getPublicKey.h" -#include "common_ui.h" +#include "ui_callbacks.h" #include "feature_performPrivacyOperation.h" unsigned int io_seproxyhal_touch_privacy_ok(void) { diff --git a/src_features/provideDynamicNetwork/network_dynamic.c b/src_features/provideDynamicNetwork/network_dynamic.c deleted file mode 100644 index 32a9db20a4..0000000000 --- a/src_features/provideDynamicNetwork/network_dynamic.c +++ /dev/null @@ -1,662 +0,0 @@ -#ifdef HAVE_DYNAMIC_NETWORKS - -#include -#include -#include "os_utils.h" -#include "os_pic.h" -#include "network.h" -#include "network_dynamic.h" -#include "shared_context.h" -#include "common_utils.h" -#include "apdu_constants.h" -#include "write.h" -#include "hash_bytes.h" -#include "lcx_hash.h" -#include "lcx_sha256.h" -#include "public_keys.h" -#ifdef HAVE_LEDGER_PKI -#include "os_pki.h" -#endif - -#define P2_NETWORK_CONFIG 0x00 -#define P2_NETWORK_ICON 0x01 -#define P2_GET_INFO 0x02 - -#define MAX_ICON_LEN 1024 - -#define TYPE_DYNAMIC_NETWORK 0x08 -#define NETWORK_STRUCT_VERSION 0x01 - -#define BLOCKCHAIN_FAMILY_ETHEREUM 0x01 - -// Tags are defined here: -// https://ledgerhq.atlassian.net/wiki/spaces/FW/pages/5039292480/Dynamic+Networks -enum { - TAG_STRUCTURE_TYPE = 0x01, - TAG_STRUCTURE_VERSION = 0x02, - TAG_BLOCKCHAIN_FAMILY = 0x51, - TAG_CHAIN_ID = 0x23, - TAG_NETWORK_NAME = 0x52, - TAG_TICKER = 0x24, - TAG_NETWORK_ICON_HASH = 0x53, - TAG_DER_SIGNATURE = 0x15, -}; - -// Signature context structure -typedef struct { - uint8_t sig_size; - const uint8_t *sig; - cx_sha256_t hash_ctx; -} s_sig_ctx; - -// Global variable to store the current slot -static uint8_t g_current_slot = 0; - -#ifdef HAVE_NBGL -typedef struct { - uint16_t received_size; - uint16_t expected_size; -} network_payload_t; - -// Global variable to store the network icons -typedef struct { - uint8_t bitmap[MAX_ICON_LEN]; - uint8_t hash[CX_SHA256_SIZE]; -} network_icon_t; -// Global structure to store the network icons -static network_icon_t g_network_icon[MAX_DYNAMIC_NETWORKS] = {0}; -// Global structure to temporary store the network icon APDU -static network_payload_t g_icon_payload = {0}; -#endif - -// Global structure to store the dynamic network information -network_info_t DYNAMIC_NETWORK_INFO[MAX_DYNAMIC_NETWORKS] = {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 APDU_RESPONSE_INVALID_DATA; \ - } \ - } while (0) -#define CHECK_FIELD_OVERFLOW(tag, field) \ - do { \ - if (field_len >= sizeof(field)) { \ - PRINTF("%s Size overflow!\n", tag); \ - return APDU_RESPONSE_INSUFFICIENT_MEMORY; \ - } \ - } 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 APDU_RESPONSE_INVALID_DATA; \ - } \ - } while (0) - -// Macro to copy the field -#define COPY_FIELD(field) \ - do { \ - memmove((void *) field, data, field_len); \ - } while (0) - -/** - * @brief Parse the STRUCTURE_TYPE value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @return APDU Response code - */ -static uint16_t parse_struct_type(const uint8_t *data, uint16_t field_len) { - CHECK_FIELD_LENGTH("STRUCTURE_TYPE", field_len, 1); - CHECK_FIELD_VALUE("STRUCTURE_TYPE", data[0], TYPE_DYNAMIC_NETWORK); - return APDU_RESPONSE_OK; -} - -/** - * @brief Parse the STRUCTURE_VERSION value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @return APDU Response code - */ -static uint16_t parse_struct_version(const uint8_t *data, uint16_t field_len) { - CHECK_FIELD_LENGTH("STRUCTURE_VERSION", field_len, 1); - CHECK_FIELD_VALUE("STRUCTURE_VERSION", data[0], NETWORK_STRUCT_VERSION); - return APDU_RESPONSE_OK; -} - -/** - * @brief Parse the BLOCKCHAIN_FAMILY value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @return APDU Response code - */ -static uint16_t parse_blockchain_family(const uint8_t *data, uint16_t field_len) { - CHECK_FIELD_LENGTH("BLOCKCHAIN_FAMILY", field_len, 1); - CHECK_FIELD_VALUE("BLOCKCHAIN_FAMILY", data[0], BLOCKCHAIN_FAMILY_ETHEREUM); - return APDU_RESPONSE_OK; -} - -/** - * @brief Parse the CHAIN_ID value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @return APDU Response code - */ -static uint16_t parse_chain_id(const uint8_t *data, uint16_t field_len) { - uint64_t chain_id; - uint64_t max_range; - uint8_t i; - - CHECK_FIELD_LENGTH("CHAIN_ID", field_len, sizeof(uint64_t)); - // Check if the chain ID is supported - // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2294.md - max_range = 0x7FFFFFFFFFFFFFDB; - chain_id = u64_from_BE(data, field_len); - // Check if the chain_id is supported - if ((chain_id > max_range) || (chain_id == 0)) { - PRINTF("Unsupported chain ID: %u\n", chain_id); - return APDU_RESPONSE_INVALID_DATA; - } - // Check if the chain_id is already registered - for (i = 0; i < MAX_DYNAMIC_NETWORKS; i++) { - if (DYNAMIC_NETWORK_INFO[i].chain_id == chain_id) { - PRINTF("CHAIN_ID already exist!\n"); - return APDU_RESPONSE_INVALID_DATA; - } - } - - DYNAMIC_NETWORK_INFO[g_current_slot].chain_id = chain_id; - return APDU_RESPONSE_OK; -} - -/** - * @brief Check the name is printable. - * - * @param[in] data buffer received - * @param[in] name Name to check - * @param[in] len Length of the name - * @return True/False - */ -static bool check_name(const uint8_t *name, uint16_t len) { - for (uint16_t i = 0; i < len; i++) { - if (!isprint(name[i])) { - return false; - } - } - return true; -} - -/** - * @brief Parse the NETWORK_NAME value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @return APDU Response code - */ -static uint16_t parse_name(const uint8_t *data, uint16_t field_len) { - CHECK_FIELD_OVERFLOW("NETWORK_NAME", DYNAMIC_NETWORK_INFO[g_current_slot].name); - // Check if the name is printable - if (!check_name(data, field_len)) { - PRINTF("NETWORK_NAME is not printable!\n"); - return APDU_RESPONSE_INVALID_DATA; - } - COPY_FIELD(DYNAMIC_NETWORK_INFO[g_current_slot].name); - return APDU_RESPONSE_OK; -} - -/** - * @brief Parse the NETWORK_TICKER value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @return APDU Response code - */ -static uint16_t parse_ticker(const uint8_t *data, uint16_t field_len) { - CHECK_FIELD_OVERFLOW("NETWORK_TICKER", DYNAMIC_NETWORK_INFO[g_current_slot].ticker); - // Check if the ticker is printable - if (!check_name(data, field_len)) { - PRINTF("NETWORK_TICKER is not printable!\n"); - return APDU_RESPONSE_INVALID_DATA; - } - COPY_FIELD(DYNAMIC_NETWORK_INFO[g_current_slot].ticker); - return APDU_RESPONSE_OK; -} - -#ifdef HAVE_NBGL -/** - * @brief Parse the NETWORK_ICON_HASH value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @return APDU Response code - */ -static uint16_t parse_icon_hash(const uint8_t *data, uint16_t field_len) { - CHECK_FIELD_LENGTH("NETWORK_ICON_HASH", field_len, CX_SHA256_SIZE); - COPY_FIELD(g_network_icon[g_current_slot].hash); - return APDU_RESPONSE_OK; -} - -/** - * @brief Check the NETWORK_ICON header. - * - * @param[in] data buffer received - * @param[in] length Length of the field value - * @return APDU Response code - */ -static uint16_t check_icon_header(const uint8_t *data, uint16_t length, uint16_t *buffer_size) { - // The chunk starts by the Image Header (8 Bytes): - // - Width (2 Bytes) - // - Height (2 Bytes) - // - BPP (1 Byte) - // - Img buffer size (3 Bytes) - if (length < 8) { - PRINTF("NETWORK_ICON header length mismatch (%d)!\n", length); - return APDU_RESPONSE_INVALID_DATA; - } - *buffer_size = 8 + data[5] + (data[6] << 8) + (data[7] << 16); - return APDU_RESPONSE_OK; -} - -/** - * @brief Print the registered network icon. - * - * Only for debug purpose. - * - */ -static void print_icon_info(void) { - PRINTF("****************************************************************************\n"); - PRINTF("[NETWORK_ICON] - Registered in slot %d: icon %dx%d (BPP %d)\n", - g_current_slot, - DYNAMIC_NETWORK_INFO[g_current_slot].icon.width, - DYNAMIC_NETWORK_INFO[g_current_slot].icon.height, - DYNAMIC_NETWORK_INFO[g_current_slot].icon.bpp); -} - -/** - * @brief Parse and check the NETWORK_ICON value. - * - * @return APDU Response code - */ -static uint16_t parse_icon_buffer(void) { - uint16_t img_len = 0; - uint16_t sw = APDU_RESPONSE_UNKNOWN; - uint8_t digest[CX_SHA256_SIZE]; - const uint8_t *data = g_network_icon[g_current_slot].bitmap; - const uint16_t field_len = g_icon_payload.received_size; - cx_err_t error = CX_INTERNAL_ERROR; - - // Check the icon header - sw = check_icon_header(data, field_len, &img_len); - if (sw != APDU_RESPONSE_OK) { - return sw; - } - CHECK_FIELD_LENGTH("NETWORK_ICON", field_len, img_len); - CHECK_FIELD_OVERFLOW("NETWORK_ICON", g_network_icon[g_current_slot].bitmap); - - // Check icon hash - CX_CHECK(cx_sha256_hash(data, field_len, digest)); - if (memcmp(digest, g_network_icon[g_current_slot].hash, CX_SHA256_SIZE) != 0) { - PRINTF("NETWORK_ICON hash mismatch!\n"); - return APDU_RESPONSE_INVALID_DATA; - } - - DYNAMIC_NETWORK_INFO[g_current_slot].icon.bitmap = - (const uint8_t *) g_network_icon[g_current_slot].bitmap; - DYNAMIC_NETWORK_INFO[g_current_slot].icon.width = U2LE(data, 0); - DYNAMIC_NETWORK_INFO[g_current_slot].icon.height = U2LE(data, 2); - // BPP is stored in the upper 4 bits of the 5th byte - DYNAMIC_NETWORK_INFO[g_current_slot].icon.bpp = data[4] >> 4; - DYNAMIC_NETWORK_INFO[g_current_slot].icon.isFile = true; - COPY_FIELD(DYNAMIC_NETWORK_INFO[g_current_slot].icon.bitmap); - print_icon_info(); - error = APDU_RESPONSE_OK; -end: - return error; -} - -/** - * @brief Init the dynamic network icon with the 1st chunk. - * - * Analyze the 1st chunk, containing the icon size - * - * @param[in] data buffer received, skip payload length - * @param[in] length of the buffer, reduced by the payload length - * @return APDU Response code - */ -static uint16_t handle_first_icon_chunk(const uint8_t *data, uint8_t length) { - uint16_t img_len = 0; - uint16_t sw = APDU_RESPONSE_UNKNOWN; - - // Reset the structures - explicit_bzero(&g_icon_payload, sizeof(g_icon_payload)); - explicit_bzero(g_network_icon[g_current_slot].bitmap, MAX_ICON_LEN); - - // Check the icon header - sw = check_icon_header(data, length, &img_len); - if (sw != APDU_RESPONSE_OK) { - return sw; - } - if (img_len > MAX_ICON_LEN) { - PRINTF("Icon size too large!\n"); - return APDU_RESPONSE_INSUFFICIENT_MEMORY; - } - g_icon_payload.expected_size = img_len; - - return APDU_RESPONSE_OK; -} - -/** - * @brief Handle icon data chunk. - * - * @param[in] data buffer received - * @param[in] length of the buffer - * @return APDU Response code - */ -static uint16_t handle_next_icon_chunk(const uint8_t *data, uint8_t length) { - if ((g_icon_payload.received_size + length) > g_icon_payload.expected_size) { - PRINTF("Payload size mismatch!\n"); - return APDU_RESPONSE_INVALID_DATA; - } - // Feed into payload - memcpy(g_network_icon[g_current_slot].bitmap + g_icon_payload.received_size, data, length); - g_icon_payload.received_size += length; - - return APDU_RESPONSE_OK; -} - -/** - * @brief Handle icon chunks. - * - * @param[in] p1 APDU parameter 1 - * @param[in] data buffer received - * @param[in] length of the buffer - * @return APDU Response code - */ -static uint16_t handle_icon_chunks(uint8_t p1, const uint8_t *data, uint8_t length) { - uint16_t sw = APDU_RESPONSE_UNKNOWN; - uint8_t hash[CX_SHA256_SIZE] = {0}; - - if (memcmp(g_network_icon[g_current_slot].hash, hash, CX_SHA256_SIZE) == 0) { - PRINTF("Error: Icon hash not set!\n"); - return APDU_RESPONSE_INVALID_DATA; - } - - // Check the received chunk index - if (p1 == P1_FIRST_CHUNK) { - // Init the with the 1st chunk - sw = handle_first_icon_chunk(data, length); - if (sw != APDU_RESPONSE_OK) { - return sw; - } - } else if (p1 != P1_FOLLOWING_CHUNK) { - PRINTF("Error: Unexpected P2 (%u)!\n", p1); - return APDU_RESPONSE_INVALID_P1_P2; - } - - // Handle the payload - sw = handle_next_icon_chunk(data, length); - if (sw != APDU_RESPONSE_OK) { - return sw; - } - if (g_icon_payload.received_size == g_icon_payload.expected_size) { - // Everything has been received - sw = parse_icon_buffer(); - } - return sw; -} -#endif - -/** - * @brief Parse the SIGNATURE value. - * - * @param[in] data buffer received - * @param[in] field_len Length of the field value - * @param[in] sig_ctx the signature context - * @return APDU Response code - */ -static uint16_t parse_signature(const uint8_t *data, uint16_t field_len, s_sig_ctx *sig_ctx) { - sig_ctx->sig_size = field_len; - sig_ctx->sig = data; - return APDU_RESPONSE_OK; -} - -/** - * @brief Verify the payload signature - * - * Verify the SHA-256 hash of the payload against the public key - * - * @param[in] sig_ctx the signature context - * @return whether it was successful - */ -static bool verify_signature(s_sig_ctx *sig_ctx) { - uint8_t hash[INT256_LENGTH]; - - if (cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH) != - CX_OK) { - return false; - } - - if (check_signature_with_pubkey("Dynamic Network", - hash, - sizeof(hash), - NULL, - 0, -#ifdef HAVE_LEDGER_PKI - // TODO: change once SDK has the enum value for this - 0x0c, -#endif - (uint8_t *) (sig_ctx->sig), - sig_ctx->sig_size) != CX_OK) { - return false; - } - return true; -} - -/** - * @brief Print the registered network. - * - * Only for debug purpose. - */ -static void print_network_info(void) { - char chain_str[sizeof(uint64_t) * 2 + 1] = {0}; - - PRINTF("****************************************************************************\n"); - u64_to_string(DYNAMIC_NETWORK_INFO[g_current_slot].chain_id, chain_str, sizeof(chain_str)); - PRINTF("[NETWORK] - Registered in slot %d: %s (%s), for chain_id %s\n", - g_current_slot, - DYNAMIC_NETWORK_INFO[g_current_slot].name, - DYNAMIC_NETWORK_INFO[g_current_slot].ticker, - chain_str); -} - -/** - * @brief Parse the TLV payload containing the Network configuration. - * - * @param[in] data buffer received - * @param[in] length of the buffer - * @return APDU Response code - */ -static uint16_t parse_tlv(const uint8_t *data, uint8_t length) { - uint16_t offset = 0; - uint16_t field_tag = 0; - uint16_t field_len = 0; - uint16_t sw = APDU_RESPONSE_INTERNAL_ERROR; - uint16_t tag_start_off; - s_sig_ctx sig_ctx = {0}; - - // Set the current slot here, because the corresponding icon will be received - // separately, after the network configuration, and should keep the same slot - g_current_slot = (g_current_slot + 1) % MAX_DYNAMIC_NETWORKS; - - // Reset the structures - explicit_bzero(&DYNAMIC_NETWORK_INFO[g_current_slot], sizeof(network_info_t)); -#ifdef HAVE_NBGL - explicit_bzero(&g_network_icon[g_current_slot], sizeof(network_icon_t)); -#endif - // Initialize the hash context - cx_sha256_init(&sig_ctx.hash_ctx); - // handle TLV payload - while (offset != length) { - if ((offset + 2) > length) { - sw = APDU_RESPONSE_INVALID_DATA; - break; - } - tag_start_off = offset; - field_tag = data[offset++]; - field_len = data[offset++]; - if ((offset + field_len) > length) { - PRINTF("Field length mismatch (%d/%d)!\n", (offset + field_len), length); - sw = APDU_RESPONSE_INVALID_DATA; - break; - } - switch (field_tag) { - case TAG_STRUCTURE_TYPE: - sw = parse_struct_type(data + offset, field_len); - break; - case TAG_STRUCTURE_VERSION: - sw = parse_struct_version(data + offset, field_len); - break; - case TAG_BLOCKCHAIN_FAMILY: - sw = parse_blockchain_family(data + offset, field_len); - break; - case TAG_CHAIN_ID: - sw = parse_chain_id(data + offset, field_len); - break; - case TAG_NETWORK_NAME: - sw = parse_name(data + offset, field_len); - break; - case TAG_TICKER: - sw = parse_ticker(data + offset, field_len); - break; - case TAG_NETWORK_ICON_HASH: -#ifdef HAVE_NBGL - sw = parse_icon_hash(data + offset, field_len); -#endif - break; - case TAG_DER_SIGNATURE: - sw = parse_signature(data + offset, field_len, &sig_ctx); - break; - default: - PRINTF("Skipping unknown tag: %d\n", field_tag); - sw = APDU_RESPONSE_OK; - break; - } - if (sw != APDU_RESPONSE_OK) { - break; - } - offset += field_len; - if (field_tag != TAG_DER_SIGNATURE) { // the signature wasn't computed on itself - hash_nbytes(data + tag_start_off, - (offset - tag_start_off), - (cx_hash_t *) &sig_ctx.hash_ctx); - } - } - if (sw == APDU_RESPONSE_OK) { - if (verify_signature(&sig_ctx) == false) { - PRINTF("Signature verification failed!\n"); - sw = APDU_RESPONSE_INVALID_DATA; - } - } - if (sw == APDU_RESPONSE_OK) { - print_network_info(); - } else { - // Reset the structure - explicit_bzero(&DYNAMIC_NETWORK_INFO[g_current_slot], sizeof(network_info_t)); - } - return sw; -} - -/** - * @brief Returns the current network configuration. - * - * @return APDU length - */ -static uint16_t handle_get_config(void) { - uint8_t chain_str[sizeof(uint64_t) * 2 + 1]; - uint32_t tx = 1; // Init to '1' because there is at least the number of networks - uint16_t nb_networks = 0; - - for (size_t i = 0; i < MAX_DYNAMIC_NETWORKS; i++) { - if (DYNAMIC_NETWORK_INFO[i].chain_id != 0) { - PRINTF("[NETWORK] - Found dynamic %s\n", DYNAMIC_NETWORK_INFO[i].name); - // Convert chain_id - explicit_bzero(chain_str, sizeof(chain_str)); - write_u64_be(chain_str, 0, DYNAMIC_NETWORK_INFO[i].chain_id); - memmove(G_io_apdu_buffer + tx, chain_str, sizeof(uint64_t)); - tx += sizeof(uint64_t); - nb_networks++; - } - } - G_io_apdu_buffer[0] = nb_networks; - - return tx; -} - -/** - * @brief Handle Network Configuration APDU. - * - * @param[in] p1 APDU parameter 1 - * @param[in] p2 APDU parameter 2 - * @param[in] data buffer received - * @param[in] length of the buffer - * @param[in] tx output length - * @return APDU Response code - */ -uint16_t handleNetworkConfiguration(uint8_t p1, - uint8_t p2, - const uint8_t *data, - uint8_t length, - unsigned int *tx) { - uint16_t sw = APDU_RESPONSE_UNKNOWN; - - switch (p2) { - case P2_NETWORK_CONFIG: - if (p1 != 0x00) { - PRINTF("Error: Unexpected P1 (%u)!\n", p1); - sw = APDU_RESPONSE_INVALID_P1_P2; - break; - } - sw = parse_tlv(data, length); - break; - - case P2_NETWORK_ICON: -#ifdef HAVE_NBGL - sw = handle_icon_chunks(p1, data, length); -#else - PRINTF("Warning: Network icon not supported!\n"); - sw = APDU_RESPONSE_OK; -#endif - break; - - case P2_GET_INFO: - if (p1 != 0x00) { - PRINTF("Error: Unexpected P1 (%u)!\n", p1); - sw = APDU_RESPONSE_INVALID_P1_P2; - break; - } - *tx = handle_get_config(); - sw = APDU_RESPONSE_OK; - break; - default: - sw = APDU_RESPONSE_INVALID_P1_P2; - break; - } - -#ifdef HAVE_NBGL - if ((sw != APDU_RESPONSE_OK) || - (g_icon_payload.received_size == g_icon_payload.expected_size)) { - explicit_bzero(&g_icon_payload, sizeof(g_icon_payload)); - } -#endif - - return sw; -} - -#endif // HAVE_DYNAMIC_NETWORKS diff --git a/src_features/provideDynamicNetwork/network_dynamic.h b/src_features/provideDynamicNetwork/network_dynamic.h deleted file mode 100644 index 4500870346..0000000000 --- a/src_features/provideDynamicNetwork/network_dynamic.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include "network.h" - -#define MAX_DYNAMIC_NETWORKS 2 // Nb configurations max to store - -extern network_info_t DYNAMIC_NETWORK_INFO[]; - -uint16_t handleNetworkConfiguration(uint8_t p1, - uint8_t p2, - const uint8_t *data, - uint8_t length, - unsigned int *tx); diff --git a/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c b/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c index 492c5244f5..b264a2ac21 100644 --- a/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c +++ b/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c @@ -1,8 +1,5 @@ -#include "shared_context.h" #include "apdu_constants.h" #include "public_keys.h" -#include "common_ui.h" -#include "os_io_seproxyhal.h" #include "network.h" #include "manage_asset_info.h" #ifdef HAVE_LEDGER_PKI diff --git a/src_features/provideNFTInformation/cmd_provideNFTInfo.c b/src_features/provideNFTInformation/cmd_provideNFTInfo.c index dc29dbddf4..3584e3b412 100644 --- a/src_features/provideNFTInformation/cmd_provideNFTInfo.c +++ b/src_features/provideNFTInformation/cmd_provideNFTInfo.c @@ -1,11 +1,7 @@ #ifdef HAVE_NFT_SUPPORT -#include "shared_context.h" #include "apdu_constants.h" #include "asset_info.h" -#include "common_utils.h" -#include "common_ui.h" -#include "os_io_seproxyhal.h" #include "network.h" #include "public_keys.h" #include "manage_asset_info.h" diff --git a/src_features/provideTrustedName/cmd_provide_trusted_name.c b/src_features/provideTrustedName/cmd_provide_trusted_name.c deleted file mode 100644 index ffb98e6713..0000000000 --- a/src_features/provideTrustedName/cmd_provide_trusted_name.c +++ /dev/null @@ -1,985 +0,0 @@ -#ifdef HAVE_TRUSTED_NAME - -#include -#include -#include -#include -#include "common_utils.h" // ARRAY_SIZE -#include "apdu_constants.h" -#include "trusted_name.h" -#include "challenge.h" -#include "mem.h" -#include "hash_bytes.h" -#include "network.h" -#include "public_keys.h" -#ifdef HAVE_LEDGER_PKI -#include "os_pki.h" -#endif - -#define STRUCT_TYPE_TRUSTED_NAME 0x03 -#define ALGO_SECP256K1 1 - -#define SLIP_44_ETHEREUM 60 - -#define DER_LONG_FORM_FLAG 0x80 // 8th bit set -#define DER_FIRST_BYTE_VALUE_MASK 0x7f - -typedef enum { TLV_TAG, TLV_LENGTH, TLV_VALUE } e_tlv_step; - -// This enum needs to be ordered the same way as the e_tlv_tag one ! -typedef enum { - STRUCT_TYPE_RCV_BIT = 0, - STRUCT_VERSION_RCV_BIT, - NOT_VALID_AFTER_RCV_BIT, - CHALLENGE_RCV_BIT, - SIGNER_KEY_ID_RCV_BIT, - SIGNER_ALGO_RCV_BIT, - SIGNATURE_RCV_BIT, - TRUSTED_NAME_RCV_BIT, - COIN_TYPE_RCV_BIT, - ADDRESS_RCV_BIT, - CHAIN_ID_RCV_BIT, - TRUSTED_NAME_TYPE_RCV_BIT, - TRUSTED_NAME_SOURCE_RCV_BIT, - NFT_ID_RCV_BIT, -} e_tlv_rcv_bit; - -#define RCV_FLAG(a) (1 << a) - -typedef enum { - STRUCT_TYPE = 0x01, - STRUCT_VERSION = 0x02, - NOT_VALID_AFTER = 0x10, - CHALLENGE = 0x12, - SIGNER_KEY_ID = 0x13, - SIGNER_ALGO = 0x14, - SIGNATURE = 0x15, - TRUSTED_NAME = 0x20, - COIN_TYPE = 0x21, - ADDRESS = 0x22, - CHAIN_ID = 0x23, - TRUSTED_NAME_TYPE = 0x70, - TRUSTED_NAME_SOURCE = 0x71, - NFT_ID = 0x72, -} e_tlv_tag; - -typedef enum { TN_KEY_ID_DOMAIN_SVC = 0x03, TN_KEY_ID_CAL = 0x06 } e_tn_key_id; - -typedef struct { - uint8_t *buf; - uint16_t size; - uint16_t expected_size; -} s_tlv_payload; - -typedef struct { - e_tlv_tag tag; - uint8_t length; - const uint8_t *value; -} s_tlv_data; - -typedef struct { - uint32_t rcv_flags; - bool valid; - uint8_t struct_version; - char *name; - uint8_t addr[ADDRESS_LENGTH]; - uint64_t chain_id; - e_name_type name_type; - e_name_source name_source; - uint8_t nft_id[INT256_LENGTH]; -} s_trusted_name_info; - -typedef struct { - e_tn_key_id key_id; - uint8_t input_sig_size; - const uint8_t *input_sig; - cx_sha256_t hash_ctx; -} s_sig_ctx; - -typedef bool(t_tlv_handler)(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx); - -typedef struct { - e_tlv_tag tag; - t_tlv_handler *func; - e_tlv_rcv_bit rcv_bit; -} s_tlv_handler; - -static s_tlv_payload g_tlv_payload = {0}; -static s_trusted_name_info g_trusted_name_info = {0}; -char g_trusted_name[TRUSTED_NAME_MAX_LENGTH + 1]; - -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; - } - return false; -} - -static bool matching_source(e_name_source source, - uint8_t source_count, - const e_name_source *sources) { - for (int i = 0; i < source_count; ++i) { - if (source == sources[i]) return true; - } - return false; -} - -static bool matching_trusted_name(const s_trusted_name_info *trusted_name, - uint8_t type_count, - const e_name_type *types, - uint8_t source_count, - const e_name_source *sources, - const uint64_t *chain_id, - const uint8_t *addr) { - switch (trusted_name->struct_version) { - case 1: - if (!matching_type(TN_TYPE_ACCOUNT, type_count, types)) { - return false; - } - if (!chain_is_ethereum_compatible(chain_id)) { - return false; - } - break; - case 2: - if (!matching_type(trusted_name->name_type, type_count, types)) { - return false; - } - if (!matching_source(trusted_name->name_source, source_count, sources)) { - return false; - } - if (*chain_id != trusted_name->chain_id) { - return false; - } - break; - } - return memcmp(addr, trusted_name->addr, ADDRESS_LENGTH) == 0; -} - -/** - * Checks if a trusted name matches the given parameters - * - * Always wipes the content of \ref g_trusted_name_info - * - * @param[in] types_count number of given trusted name types - * @param[in] types given trusted name types - * @param[in] chain_id given chain ID - * @param[in] addr given address - * @return whether there is or not - */ -const char *get_trusted_name(uint8_t type_count, - const e_name_type *types, - uint8_t source_count, - const e_name_source *sources, - const uint64_t *chain_id, - const uint8_t *addr) { - const char *ret = NULL; - - if (g_trusted_name_info.rcv_flags != 0) { - if (matching_trusted_name(&g_trusted_name_info, - type_count, - types, - source_count, - sources, - chain_id, - addr)) { - ret = g_trusted_name_info.name; - } - explicit_bzero(&g_trusted_name_info, sizeof(g_trusted_name_info)); - } - return ret; -} - -/** - * Get uint from tlv data - * - * Get an unsigned integer from variable length tlv data (up to 4 bytes) - * - * @param[in] data tlv data - * @param[out] value the returned value - * @return whether it was successful - */ -static bool get_uint_from_data(const s_tlv_data *data, uint32_t *value) { - uint8_t size_diff; - uint8_t buffer[sizeof(uint32_t)]; - - if (data->length > sizeof(buffer)) { - PRINTF("Unexpectedly long value (%u bytes) for tag 0x%x\n", data->length, data->tag); - return false; - } - size_diff = sizeof(buffer) - data->length; - memset(buffer, 0, size_diff); - memcpy(buffer + size_diff, data->value, data->length); - *value = U4BE(buffer, 0); - return true; -} - -/** - * Handler for tag \ref STRUCT_TYPE - * - * @param[in] data the tlv data - * @param[] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_struct_type(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - - (void) trusted_name_info; - (void) sig_ctx; - if (!get_uint_from_data(data, &value)) { - return false; - } - return (value == STRUCT_TYPE_TRUSTED_NAME); -} - -/** - * Handler for tag \ref NOT_VALID_AFTER - * - * @param[in] data the tlv data - * @param[] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_not_valid_after(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - const uint8_t app_version[] = {MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION}; - - (void) trusted_name_info; - (void) sig_ctx; - if (data->length != ARRAYLEN(app_version)) { - return false; - } - for (int i = 0; i < (int) ARRAYLEN(app_version); ++i) { - if (data->value[i] < app_version[i]) { - PRINTF("Expired trusted name : %u.%u.%u < %u.%u.%u\n", - data->value[0], - data->value[1], - data->value[2], - app_version[0], - app_version[1], - app_version[2]); - return false; - } - } - return true; -} - -/** - * Handler for tag \ref STRUCT_VERSION - * - * @param[in] data the tlv data - * @param[out] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_struct_version(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - - (void) sig_ctx; - if (!get_uint_from_data(data, &value) || (value > UINT8_MAX)) { - return false; - } - trusted_name_info->struct_version = value; - return true; -} - -/** - * Handler for tag \ref CHALLENGE - * - * @param[in] data the tlv data - * @param[] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_challenge(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - (void) trusted_name_info; - (void) sig_ctx; - - if (!get_uint_from_data(data, &value)) { - return false; - } - return (value == get_challenge()); -} - -/** - * Handler for tag \ref SIGNER_KEY_ID - * - * @param[in] data the tlv data - * @param[] trusted_name_info the trusted name information - * @param[out] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_sign_key_id(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - (void) trusted_name_info; - - if (!get_uint_from_data(data, &value) || (value > UINT8_MAX)) { - return false; - } - sig_ctx->key_id = value; - return true; -} - -/** - * Handler for tag \ref SIGNER_ALGO - * - * @param[in] data the tlv data - * @param[] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_sign_algo(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - - (void) trusted_name_info; - (void) sig_ctx; - if (!get_uint_from_data(data, &value)) { - return false; - } - return (value == ALGO_SECP256K1); -} - -/** - * Handler for tag \ref SIGNATURE - * - * @param[in] data the tlv data - * @param[] trusted_name_info the trusted name information - * @param[out] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_signature(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - (void) trusted_name_info; - sig_ctx->input_sig_size = data->length; - sig_ctx->input_sig = data->value; - return true; -} - -/** - * Tests if the given account name character is valid (in our subset of allowed characters) - * - * @param[in] c given character - * @return whether the character is valid - */ -static bool is_valid_account_character(char c) { - if (isalpha((int) c)) { - if (!islower((int) c)) { - return false; - } - } else if (!isdigit((int) c)) { - switch (c) { - case '.': - case '-': - case '_': - break; - default: - return false; - } - } - return true; -} - -/** - * Handler for tag \ref TRUSTED_NAME - * - * @param[in] data the tlv data - * @param[out] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_trusted_name(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - (void) sig_ctx; - if (data->length > TRUSTED_NAME_MAX_LENGTH) { - PRINTF("Domain name too long! (%u)\n", data->length); - return false; - } - if ((trusted_name_info->struct_version == 1) || - (trusted_name_info->name_type == TN_TYPE_ACCOUNT)) { - // TODO: Remove once other domain name providers are supported - if ((data->length < 5) || - (strncmp(".eth", (char *) &data->value[data->length - 4], 4) != 0)) { - PRINTF("Unexpected TLD!\n"); - return false; - } - for (int idx = 0; idx < data->length; ++idx) { - if (!is_valid_account_character(data->value[idx])) { - PRINTF("Domain name contains non-allowed character! (0x%x)\n", data->value[idx]); - return false; - } - trusted_name_info->name[idx] = data->value[idx]; - } - } else { - memcpy(trusted_name_info->name, data->value, data->length); - } - trusted_name_info->name[data->length] = '\0'; - return true; -} - -/** - * Handler for tag \ref COIN_TYPE - * - * @param[in] data the tlv data - * @param[] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_coin_type(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - - (void) trusted_name_info; - (void) sig_ctx; - if (!get_uint_from_data(data, &value)) { - return false; - } - return (value == SLIP_44_ETHEREUM); -} - -/** - * Handler for tag \ref ADDRESS - * - * @param[in] data the tlv data - * @param[out] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_address(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - (void) sig_ctx; - if (data->length != ADDRESS_LENGTH) { - return false; - } - memcpy(trusted_name_info->addr, data->value, ADDRESS_LENGTH); - return true; -} - -/** - * Handler for tag \ref CHAIN_ID - * - * @param[in] data the tlv data - * @param[out] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_chain_id(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - (void) sig_ctx; - trusted_name_info->chain_id = u64_from_BE(data->value, data->length); - return true; -} - -/** - * Handler for tag \ref TRUSTED_NAME_TYPE - * - * @param[in] data the tlv data - * @param[out] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_trusted_name_type(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - - (void) trusted_name_info; - (void) sig_ctx; - if (!get_uint_from_data(data, &value) || (value > UINT8_MAX)) { - return false; - } - switch (value) { - case TN_TYPE_ACCOUNT: - case TN_TYPE_CONTRACT: - break; - case TN_TYPE_NFT_COLLECTION: - case TN_TYPE_TOKEN: - case TN_TYPE_WALLET: - case TN_TYPE_CONTEXT_ADDRESS: - default: - PRINTF("Error: unsupported trusted name type (%u)!\n", value); - return false; - } - trusted_name_info->name_type = value; - return true; -} - -/** - * Handler for tag \ref TRUSTED_NAME_SOURCE - * - * @param[in] data the tlv data - * @param[out] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_trusted_name_source(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - uint32_t value; - - (void) trusted_name_info; - (void) sig_ctx; - if (!get_uint_from_data(data, &value) || (value > UINT8_MAX)) { - return false; - } - switch (value) { - case TN_SOURCE_CAL: - case TN_SOURCE_ENS: - break; - case TN_SOURCE_LAB: - case TN_SOURCE_UD: - case TN_SOURCE_FN: - case TN_SOURCE_DNS: - case TN_SOURCE_DYNAMIC_RESOLVER: - default: - PRINTF("Error: unsupported trusted name source (%u)!\n", value); - return false; - } - trusted_name_info->name_source = value; - return true; -} - -/** - * Handler for tag \ref NFT_ID - * - * @param[in] data the tlv data - * @param[out] trusted_name_info the trusted name information - * @param[] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_nft_id(const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - size_t diff; - - (void) trusted_name_info; - (void) sig_ctx; - if (data->length > sizeof(trusted_name_info->nft_id)) { - return false; - } - diff = sizeof(trusted_name_info->nft_id) - data->length; - memmove(trusted_name_info->nft_id + diff, data->value, data->length); - explicit_bzero(trusted_name_info->nft_id, diff); - return true; // unhandled for now -} - -/** - * Verify the signature context - * - * Verify the SHA-256 hash of the payload against the public key - * - * @param[in] sig_ctx the signature context - * @return whether it was successful - */ -static bool verify_signature(const s_sig_ctx *sig_ctx) { - uint8_t hash[INT256_LENGTH]; - cx_err_t error = CX_INTERNAL_ERROR; - bool ret_code = false; - const uint8_t *pk; - size_t pk_size; - - switch (sig_ctx->key_id) { - case TN_KEY_ID_DOMAIN_SVC: - pk = TRUSTED_NAME_PUB_KEY; - pk_size = sizeof(TRUSTED_NAME_PUB_KEY); - break; - case TN_KEY_ID_CAL: - pk = LEDGER_SIGNATURE_PUBLIC_KEY; - pk_size = sizeof(LEDGER_SIGNATURE_PUBLIC_KEY); - break; - default: - PRINTF("Error: Unknown metadata key ID %u\n", sig_ctx->key_id); - return false; - } - - CX_CHECK( - cx_hash_no_throw((cx_hash_t *) &sig_ctx->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH)); - - CX_CHECK(check_signature_with_pubkey("Trusted Name", - hash, - sizeof(hash), - pk, - pk_size, -#ifdef HAVE_LEDGER_PKI - CERTIFICATE_PUBLIC_KEY_USAGE_TRUSTED_NAME, -#endif - (uint8_t *) (sig_ctx->input_sig), - sig_ctx->input_sig_size)); - - ret_code = true; -end: - return ret_code; -} - -/** - * Calls the proper handler for the given TLV data - * - * Checks if there is a proper handler function for the given TLV tag and then calls it - * - * @param[in] handlers list of tag / handler function pairs - * @param[in] handler_count number of handlers - * @param[in] data the TLV data - * @param[out] trusted_name_info the trusted name information - * @param[out] sig_ctx the signature context - * @return whether it was successful - */ -static bool handle_tlv_data(s_tlv_handler *handlers, - int handler_count, - const s_tlv_data *data, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - t_tlv_handler *fptr; - - // check if a handler exists for this tag - for (int idx = 0; idx < handler_count; ++idx) { - if (handlers[idx].tag == data->tag) { - trusted_name_info->rcv_flags |= RCV_FLAG(handlers[idx].rcv_bit); - fptr = PIC(handlers[idx].func); - if (!(*fptr)(data, trusted_name_info, sig_ctx)) { - PRINTF("Error while handling tag 0x%x\n", handlers[idx].tag); - return false; - } - break; - } - } - return true; -} - -/** - * Verify the validity of the received trusted struct - * - * @param[in] trusted_name_info the trusted name information - * @return whether the struct is valid - */ -static bool verify_struct(const s_trusted_name_info *trusted_name_info) { - uint32_t required_flags; - - if (!(RCV_FLAG(STRUCT_VERSION_RCV_BIT) & trusted_name_info->rcv_flags)) { - PRINTF("Error: no struct version specified!\n"); - return false; - } - required_flags = RCV_FLAG(STRUCT_TYPE_RCV_BIT) | RCV_FLAG(STRUCT_VERSION_RCV_BIT) | - RCV_FLAG(SIGNER_KEY_ID_RCV_BIT) | RCV_FLAG(SIGNER_ALGO_RCV_BIT) | - RCV_FLAG(SIGNATURE_RCV_BIT) | RCV_FLAG(TRUSTED_NAME_RCV_BIT) | - RCV_FLAG(ADDRESS_RCV_BIT); - switch (trusted_name_info->struct_version) { - case 1: - required_flags |= RCV_FLAG(CHALLENGE_RCV_BIT) | RCV_FLAG(COIN_TYPE_RCV_BIT); - if ((trusted_name_info->rcv_flags & required_flags) != required_flags) { - return false; - } - break; - case 2: - required_flags |= RCV_FLAG(CHAIN_ID_RCV_BIT) | RCV_FLAG(TRUSTED_NAME_TYPE_RCV_BIT) | - RCV_FLAG(TRUSTED_NAME_SOURCE_RCV_BIT); - if ((trusted_name_info->rcv_flags & required_flags) != required_flags) { - return false; - } - switch (trusted_name_info->name_type) { - case TN_TYPE_ACCOUNT: - if (trusted_name_info->name_source == TN_SOURCE_CAL) { - PRINTF("Error: cannot accept an account name from the CAL!\n"); - return false; - } - if (!(trusted_name_info->rcv_flags & RCV_FLAG(CHALLENGE_RCV_BIT))) { - PRINTF("Error: trusted account name requires a challenge!\n"); - return false; - } - break; - case TN_TYPE_CONTRACT: - if (trusted_name_info->name_source != TN_SOURCE_CAL) { - PRINTF("Error: cannot accept a contract name from given source (%u)!\n", - trusted_name_info->name_source); - return false; - } - break; - default: - return false; - } - break; - default: - PRINTF("Error: unsupported trusted name struct version (%u) !\n", - trusted_name_info->struct_version); - return false; - } - return true; -} - -/** Parse DER-encoded value - * - * Parses a DER-encoded value (up to 4 bytes long) - * https://en.wikipedia.org/wiki/X.690 - * - * @param[in] payload the TLV payload - * @param[in,out] offset the payload offset - * @param[out] value the parsed value - * @return whether it was successful - */ -static bool parse_der_value(const s_tlv_payload *payload, size_t *offset, uint32_t *value) { - bool ret = false; - uint8_t byte_length; - uint8_t buf[sizeof(*value)]; - - if (value != NULL) { - if (payload->buf[*offset] & DER_LONG_FORM_FLAG) { // long form - byte_length = payload->buf[*offset] & DER_FIRST_BYTE_VALUE_MASK; - *offset += 1; - if ((*offset + byte_length) > payload->size) { - PRINTF("TLV payload too small for DER encoded value\n"); - } else { - if (byte_length > sizeof(buf) || byte_length == 0) { - PRINTF("Unexpectedly long DER-encoded value (%u bytes)\n", byte_length); - } else { - memset(buf, 0, (sizeof(buf) - byte_length)); - memcpy(buf + (sizeof(buf) - byte_length), &payload->buf[*offset], byte_length); - *value = U4BE(buf, 0); - *offset += byte_length; - ret = true; - } - } - } else { // short form - *value = payload->buf[*offset]; - *offset += 1; - ret = true; - } - } - return ret; -} - -/** - * Get DER-encoded value as an uint8 - * - * Parses the value and checks if it fits in the given \ref uint8_t value - * - * @param[in] payload the TLV payload - * @param[in,out] offset - * @param[out] value the parsed value - * @return whether it was successful - */ -static bool get_der_value_as_uint8(const s_tlv_payload *payload, size_t *offset, uint8_t *value) { - bool ret = false; - uint32_t tmp_value; - - if (value != NULL) { - if (!parse_der_value(payload, offset, &tmp_value)) { - } else { - if (tmp_value <= UINT8_MAX) { - *value = tmp_value; - ret = true; - } else { - PRINTF("TLV DER-encoded value larger than 8 bits\n"); - } - } - } - return ret; -} - -/** - * Parse the TLV payload - * - * Does the TLV parsing but also the SHA-256 hash of the payload. - * - * @param[in] payload the raw TLV payload - * @param[out] trusted_name_info the trusted name information - * @param[out] sig_ctx the signature context - * @return whether it was successful - */ -static bool parse_tlv(const s_tlv_payload *payload, - s_trusted_name_info *trusted_name_info, - s_sig_ctx *sig_ctx) { - s_tlv_handler handlers[] = { - {.tag = STRUCT_TYPE, .func = &handle_struct_type}, - {.tag = STRUCT_VERSION, .func = &handle_struct_version}, - {.tag = NOT_VALID_AFTER, .func = &handle_not_valid_after}, - {.tag = CHALLENGE, .func = &handle_challenge}, - {.tag = SIGNER_KEY_ID, .func = &handle_sign_key_id}, - {.tag = SIGNER_ALGO, .func = &handle_sign_algo}, - {.tag = SIGNATURE, .func = &handle_signature}, - {.tag = TRUSTED_NAME, .func = &handle_trusted_name}, - {.tag = COIN_TYPE, .func = &handle_coin_type}, - {.tag = ADDRESS, .func = &handle_address}, - {.tag = CHAIN_ID, .func = &handle_chain_id}, - {.tag = TRUSTED_NAME_TYPE, .func = &handle_trusted_name_type}, - {.tag = TRUSTED_NAME_SOURCE, .func = &handle_trusted_name_source}, - {.tag = NFT_ID, .func = &handle_nft_id}, - }; - e_tlv_step step = TLV_TAG; - s_tlv_data data = {0}; - size_t offset = 0; - size_t tag_start_off; - - for (size_t i = 0; i < ARRAYLEN(handlers); ++i) handlers[i].rcv_bit = i; - cx_sha256_init(&sig_ctx->hash_ctx); - // handle TLV payload - while (offset < payload->size) { - switch (step) { - case TLV_TAG: - tag_start_off = offset; - if (!get_der_value_as_uint8(payload, &offset, &data.tag)) { - return false; - } - step = TLV_LENGTH; - break; - - case TLV_LENGTH: - if (!get_der_value_as_uint8(payload, &offset, &data.length)) { - return false; - } - step = TLV_VALUE; - break; - - case TLV_VALUE: - if ((offset + data.length) > payload->size) { - PRINTF("Error: value would go beyond the TLV payload!\n"); - return false; - } - data.value = &payload->buf[offset]; - if (!handle_tlv_data(handlers, - ARRAY_SIZE(handlers), - &data, - trusted_name_info, - sig_ctx)) { - return false; - } - offset += data.length; - if (data.tag != SIGNATURE) { // the signature wasn't computed on itself - hash_nbytes(&payload->buf[tag_start_off], - (offset - tag_start_off), - (cx_hash_t *) &sig_ctx->hash_ctx); - } - step = TLV_TAG; - break; - - default: - return false; - } - } - if (step != TLV_TAG) { - PRINTF("Error: unexpected data at the end of the TLV payload!\n"); - return false; - } - return verify_struct(trusted_name_info); -} - -/** - * Allocate and assign TLV payload - * - * @param[in] payload payload structure - * @param[in] size size of the payload - * @return whether it was successful - */ -static bool alloc_payload(s_tlv_payload *payload, uint16_t size) { - if ((payload->buf = mem_alloc(size)) == NULL) { - return false; - } - payload->expected_size = size; - return true; -} - -/** - * Deallocate and unassign TLV payload - * - * @param[in] payload payload structure - */ -static void free_payload(s_tlv_payload *payload) { - mem_dealloc(payload->expected_size); - memset(payload, 0, sizeof(*payload)); -} - -static bool handle_first_chunk(const uint8_t **data, - uint8_t *length, - s_tlv_payload *payload, - uint16_t *sw) { - // check if no payload is already in memory - if (payload->buf != NULL) { - free_payload(payload); - *sw = APDU_RESPONSE_INVALID_P1_P2; - return false; - } - - // check if we at least get the size - if (*length < sizeof(payload->expected_size)) { - *sw = APDU_RESPONSE_INVALID_DATA; - return false; - } - if (!alloc_payload(payload, U2BE(*data, 0))) { - *sw = APDU_RESPONSE_INSUFFICIENT_MEMORY; - return false; - } - - // skip the size so we can process it like a following chunk - *data += sizeof(payload->expected_size); - *length -= sizeof(payload->expected_size); - return true; -} - -/** - * Handle trusted name APDU - * - * @param[in] p1 first APDU instruction parameter - * @param[in] data APDU payload - * @param[in] length payload size - */ -uint16_t handle_provide_trusted_name(uint8_t p1, const uint8_t *data, uint8_t length) { - s_sig_ctx sig_ctx; - uint16_t sw = APDU_NO_RESPONSE; - - if (p1 == P1_FIRST_CHUNK) { - if (!handle_first_chunk(&data, &length, &g_tlv_payload, &sw)) { - return sw; - } - } else { - // check if a payload is already in memory - if (g_tlv_payload.buf == NULL) { - return APDU_RESPONSE_INVALID_P1_P2; - } - } - - if ((g_tlv_payload.size + length) > g_tlv_payload.expected_size) { - free_payload(&g_tlv_payload); - PRINTF("TLV payload size mismatch!\n"); - return APDU_RESPONSE_INVALID_DATA; - } - // feed into tlv payload - memcpy(g_tlv_payload.buf + g_tlv_payload.size, data, length); - g_tlv_payload.size += length; - - // everything has been received - if (g_tlv_payload.size == g_tlv_payload.expected_size) { - g_trusted_name_info.name = g_trusted_name; - if (!parse_tlv(&g_tlv_payload, &g_trusted_name_info, &sig_ctx) || - !verify_signature(&sig_ctx)) { - free_payload(&g_tlv_payload); - roll_challenge(); // prevent brute-force guesses - g_trusted_name_info.rcv_flags = 0; - return APDU_RESPONSE_INVALID_DATA; - } - PRINTF("Registered : %s => %.*h\n", - g_trusted_name_info.name, - ADDRESS_LENGTH, - g_trusted_name_info.addr); - free_payload(&g_tlv_payload); - roll_challenge(); // prevent replays - } - return APDU_RESPONSE_OK; -} - -#endif // HAVE_TRUSTED_NAME diff --git a/src_features/provide_enum_value/cmd_enum_value.c b/src_features/provide_enum_value/cmd_enum_value.c index 33bc68bd8a..4f88b8d090 100644 --- a/src_features/provide_enum_value/cmd_enum_value.c +++ b/src_features/provide_enum_value/cmd_enum_value.c @@ -1,22 +1,20 @@ #ifdef HAVE_ENUM_VALUE -#include #include "cmd_enum_value.h" #include "apdu_constants.h" -#include "read.h" #include "mem.h" #include "enum_value.h" #include "tlv_apdu.h" #include "tlv.h" -bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) { +static bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) { + bool parsing_ret; s_enum_value_ctx ctx = {0}; cx_sha256_init(&ctx.struct_hash); - if (!tlv_parse(payload, size, (f_tlv_data_handler) &handle_enum_value_struct, &ctx)) { - return false; - } + parsing_ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_enum_value_struct, &ctx); if (to_free) mem_dealloc(sizeof(size)); + if (!parsing_ret) return false; if (!verify_enum_value_struct(&ctx)) { return false; } diff --git a/src_features/provide_enum_value/enum_value.c b/src_features/provide_enum_value/enum_value.c index 84c34d40e0..50e967d2d4 100644 --- a/src_features/provide_enum_value/enum_value.c +++ b/src_features/provide_enum_value/enum_value.c @@ -1,6 +1,5 @@ #ifdef HAVE_ENUM_VALUE -#include #include "enum_value.h" #include "read.h" #include "public_keys.h" @@ -156,8 +155,7 @@ bool verify_enum_value_struct(const s_enum_value_ctx *context) { NULL, 0, #ifdef HAVE_LEDGER_PKI - // TODO: change once SDK has the enum value for this - 0x0b, + CERTIFICATE_PUBLIC_KEY_USAGE_CALLDATA, #endif (uint8_t *) context->enum_value.signature, context->enum_value.signature_length) != CX_OK) { diff --git a/src_features/provide_enum_value/enum_value.h b/src_features/provide_enum_value/enum_value.h index 0ce6a64c23..529469de72 100644 --- a/src_features/provide_enum_value/enum_value.h +++ b/src_features/provide_enum_value/enum_value.h @@ -6,6 +6,7 @@ #include "plugin_utils.h" // SELECTOR_SIZE #include "tlv.h" #include "cx.h" +#include "signature.h" typedef struct { uint64_t chain_id; @@ -20,7 +21,7 @@ typedef struct { uint8_t version; s_enum_value_entry entry; uint8_t signature_length; - uint8_t signature[73]; + uint8_t signature[ECDSA_SIGNATURE_MAX_LENGTH]; } s_enum_value; typedef struct { diff --git a/src_features/provide_network_info/cmd_network_info.c b/src_features/provide_network_info/cmd_network_info.c new file mode 100644 index 0000000000..9026c1f643 --- /dev/null +++ b/src_features/provide_network_info/cmd_network_info.c @@ -0,0 +1,321 @@ +#ifdef HAVE_DYNAMIC_NETWORKS + +#include +#include "cmd_network_info.h" +#include "apdu_constants.h" +#include "network_info.h" +#include "write.h" +#include "tlv_apdu.h" +#include "mem.h" + +#define P2_NETWORK_CONFIG 0x00 +#define P2_NETWORK_ICON 0x01 +#define P2_GET_INFO 0x02 + +#define MAX_ICON_LEN 1024 + +#ifdef HAVE_NBGL +typedef struct { + uint16_t received_size; + uint16_t expected_size; +} network_payload_t; + +static uint8_t g_network_icon_bitmap[MAX_DYNAMIC_NETWORKS][MAX_ICON_LEN] = {0}; +// Global structure to temporary store the network icon APDU +static network_payload_t g_icon_payload = {0}; +#endif + +#ifdef HAVE_NBGL +/** + * @brief Check the NETWORK_ICON header. + * + * @param[in] data buffer received + * @param[in] length Length of the field value + * @return APDU Response code + */ +static bool check_icon_header(const uint8_t *data, uint16_t length, uint16_t *buffer_size) { + // The chunk starts by the Image Header (8 Bytes): + // - Width (2 Bytes) + // - Height (2 Bytes) + // - BPP (1 Byte) + // - Img buffer size (3 Bytes) + if (length < 8) { + PRINTF("NETWORK_ICON header length mismatch (%d)!\n", length); + return false; + } + *buffer_size = 8 + data[5] + (data[6] << 8) + (data[7] << 16); + return true; +} + +/** + * @brief Print the registered network icon. + * + * Only for debug purpose. + * + */ +static void print_icon_info(void) { + PRINTF("****************************************************************************\n"); + PRINTF("[NETWORK_ICON] - Registered in slot %d: icon %dx%d (BPP %d)\n", + g_current_network_slot, + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.width, + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.height, + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.bpp); +} + +/** + * @brief Parse and check the NETWORK_ICON value. + * + * @return whether it was successful or not + */ +static bool parse_icon_buffer(void) { + uint16_t img_len = 0; + uint8_t digest[CX_SHA256_SIZE]; + const uint8_t *data = g_network_icon_bitmap[g_current_network_slot]; + const uint16_t field_len = g_icon_payload.received_size; + + // Check the icon header + if (!check_icon_header(data, field_len, &img_len)) { + return false; + } + if (field_len != img_len) { + return false; + } + + if (field_len >= sizeof(g_network_icon_bitmap[g_current_network_slot])) { + return false; + } + + // Check icon hash + if (cx_sha256_hash(data, field_len, digest) != CX_OK) { + return false; + } + if (memcmp(digest, g_network_icon_hash[g_current_network_slot], CX_SHA256_SIZE) != 0) { + PRINTF("NETWORK_ICON hash mismatch!\n"); + return false; + } + + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.bitmap = + (const uint8_t *) g_network_icon_bitmap[g_current_network_slot]; + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.width = U2LE(data, 0); + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.height = U2LE(data, 2); + // BPP is stored in the upper 4 bits of the 5th byte + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.bpp = data[4] >> 4; + DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.isFile = true; + memcpy((uint8_t *) DYNAMIC_NETWORK_INFO[g_current_network_slot].icon.bitmap, data, field_len); + print_icon_info(); + return true; +} + +/** + * @brief Init the dynamic network icon with the 1st chunk. + * + * Analyze the 1st chunk, containing the icon size + * + * @param[in] data buffer received, skip payload length + * @param[in] length of the buffer, reduced by the payload length + * @return APDU Response code + */ +static uint16_t handle_first_icon_chunk(const uint8_t *data, uint8_t length) { + uint16_t img_len = 0; + + // Reset the structures + explicit_bzero(&g_icon_payload, sizeof(g_icon_payload)); + explicit_bzero(g_network_icon_bitmap[g_current_network_slot], MAX_ICON_LEN); + + // Check the icon header + if (!check_icon_header(data, length, &img_len)) { + return APDU_RESPONSE_INVALID_DATA; + } + if (img_len > MAX_ICON_LEN) { + PRINTF("Icon size too large!\n"); + return APDU_RESPONSE_INSUFFICIENT_MEMORY; + } + g_icon_payload.expected_size = img_len; + + return APDU_RESPONSE_OK; +} + +/** + * @brief Handle icon data chunk. + * + * @param[in] data buffer received + * @param[in] length of the buffer + * @return APDU Response code + */ +static uint16_t handle_next_icon_chunk(const uint8_t *data, uint8_t length) { + if ((g_icon_payload.received_size + length) > g_icon_payload.expected_size) { + PRINTF("Payload size mismatch!\n"); + return APDU_RESPONSE_INVALID_DATA; + } + // Feed into payload + memcpy(g_network_icon_bitmap[g_current_network_slot] + g_icon_payload.received_size, + data, + length); + g_icon_payload.received_size += length; + + return APDU_RESPONSE_OK; +} + +/** + * @brief Handle icon chunks. + * + * @param[in] p1 APDU parameter 1 + * @param[in] data buffer received + * @param[in] length of the buffer + * @return APDU Response code + */ +static uint16_t handle_icon_chunks(uint8_t p1, const uint8_t *data, uint8_t length) { + uint16_t sw; + uint8_t hash[CX_SHA256_SIZE] = {0}; + + if (memcmp(g_network_icon_hash[g_current_network_slot], hash, CX_SHA256_SIZE) == 0) { + PRINTF("Error: Icon hash not set!\n"); + return APDU_RESPONSE_INVALID_DATA; + } + + // Check the received chunk index + if (p1 == P1_FIRST_CHUNK) { + // Init the with the 1st chunk + sw = handle_first_icon_chunk(data, length); + if (sw != APDU_RESPONSE_OK) { + return sw; + } + } else if (p1 != P1_FOLLOWING_CHUNK) { + PRINTF("Error: Unexpected P2 (%u)!\n", p1); + return APDU_RESPONSE_INVALID_P1_P2; + } + + // Handle the payload + sw = handle_next_icon_chunk(data, length); + if (sw != APDU_RESPONSE_OK) { + return sw; + } + if (g_icon_payload.received_size == g_icon_payload.expected_size) { + // Everything has been received + if (!parse_icon_buffer()) { + return APDU_RESPONSE_INVALID_DATA; + } + } + return APDU_RESPONSE_OK; +} +#endif + +/** + * @brief Print the registered network. + * + * Only for debug purpose. + */ +static void print_network_info(void) { + char chain_str[sizeof(uint64_t) * 2 + 1] = {0}; + + PRINTF("****************************************************************************\n"); + u64_to_string(DYNAMIC_NETWORK_INFO[g_current_network_slot].chain_id, + chain_str, + sizeof(chain_str)); + PRINTF("[NETWORK] - Registered in slot %u: \"%s\" (%s), for chain_id %s\n", + g_current_network_slot, + DYNAMIC_NETWORK_INFO[g_current_network_slot].name, + DYNAMIC_NETWORK_INFO[g_current_network_slot].ticker, + chain_str); +} + +/** + * @brief Returns the current network configuration. + * + * @return APDU length + */ +static uint16_t handle_get_config(void) { + uint8_t chain_str[sizeof(uint64_t) * 2 + 1]; + uint32_t tx = 1; // Init to '1' because there is at least the number of networks + uint16_t nb_networks = 0; + + for (size_t i = 0; i < MAX_DYNAMIC_NETWORKS; i++) { + if (DYNAMIC_NETWORK_INFO[i].chain_id != 0) { + PRINTF("[NETWORK] - Found dynamic %s\n", DYNAMIC_NETWORK_INFO[i].name); + // Convert chain_id + explicit_bzero(chain_str, sizeof(chain_str)); + write_u64_be(chain_str, 0, DYNAMIC_NETWORK_INFO[i].chain_id); + memmove(G_io_apdu_buffer + tx, chain_str, sizeof(uint64_t)); + tx += sizeof(uint64_t); + nb_networks++; + } + } + G_io_apdu_buffer[0] = nb_networks; + + return tx; +} + +static bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) { + bool parsing_ret; + s_network_info_ctx ctx = {0}; + + // Initialize the hash context + cx_sha256_init(&ctx.hash_ctx); + parsing_ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_network_info_struct, &ctx); + if (to_free) mem_dealloc(sizeof(size)); + if (!parsing_ret || !verify_network_info_struct(&ctx)) { + return false; + } + print_network_info(); + return true; +} + +/** + * @brief Handle Network Configuration APDU. + * + * @param[in] p1 APDU parameter 1 + * @param[in] p2 APDU parameter 2 + * @param[in] data buffer received + * @param[in] length of the buffer + * @param[in] tx output length + * @return APDU Response code + */ +uint16_t handle_network_info(uint8_t p1, + uint8_t p2, + const uint8_t *data, + uint8_t length, + unsigned int *tx) { + uint16_t sw = APDU_RESPONSE_UNKNOWN; + + switch (p2) { + case P2_NETWORK_CONFIG: + if (!tlv_from_apdu(p1 == P1_FIRST_CHUNK, length, data, &handle_tlv_payload)) { + return APDU_RESPONSE_INVALID_DATA; + } + sw = APDU_RESPONSE_OK; + break; + + case P2_NETWORK_ICON: +#ifdef HAVE_NBGL + sw = handle_icon_chunks(p1, data, length); +#else + PRINTF("Warning: Network icon not supported!\n"); + sw = APDU_RESPONSE_OK; +#endif + break; + + case P2_GET_INFO: + if (p1 != 0x00) { + PRINTF("Error: Unexpected P1 (%u)!\n", p1); + sw = APDU_RESPONSE_INVALID_P1_P2; + break; + } + *tx = handle_get_config(); + sw = APDU_RESPONSE_OK; + break; + default: + sw = APDU_RESPONSE_INVALID_P1_P2; + break; + } + +#ifdef HAVE_NBGL + if ((sw != APDU_RESPONSE_OK) || + (g_icon_payload.received_size == g_icon_payload.expected_size)) { + explicit_bzero(&g_icon_payload, sizeof(g_icon_payload)); + } +#endif + + return sw; +} + +#endif // HAVE_DYNAMIC_NETWORKS diff --git a/src_features/provide_network_info/cmd_network_info.h b/src_features/provide_network_info/cmd_network_info.h new file mode 100644 index 0000000000..a22e8a18e5 --- /dev/null +++ b/src_features/provide_network_info/cmd_network_info.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +uint16_t handle_network_info(uint8_t p1, + uint8_t p2, + const uint8_t *data, + uint8_t length, + unsigned int *tx); diff --git a/src_features/provide_network_info/network_info.c b/src_features/provide_network_info/network_info.c new file mode 100644 index 0000000000..076afe50d1 --- /dev/null +++ b/src_features/provide_network_info/network_info.c @@ -0,0 +1,282 @@ +#ifdef HAVE_DYNAMIC_NETWORKS + +#include "network_info.h" +#include "utils.h" +#include "read.h" +#include "hash_bytes.h" +#include "public_keys.h" + +#define TYPE_DYNAMIC_NETWORK 0x08 +#define NETWORK_STRUCT_VERSION 0x01 + +#define BLOCKCHAIN_FAMILY_ETHEREUM 0x01 + +// Tags are defined here: +// https://ledgerhq.atlassian.net/wiki/spaces/FW/pages/5039292480/Dynamic+Networks +enum { + TAG_STRUCTURE_TYPE = 0x01, + TAG_STRUCTURE_VERSION = 0x02, + TAG_BLOCKCHAIN_FAMILY = 0x51, + TAG_CHAIN_ID = 0x23, + TAG_NETWORK_NAME = 0x52, + TAG_TICKER = 0x24, + TAG_NETWORK_ICON_HASH = 0x53, + TAG_DER_SIGNATURE = 0x15, +}; + +// Global variable to store the current slot +uint8_t g_current_network_slot = 0; + +#ifdef HAVE_NBGL +uint8_t g_network_icon_hash[MAX_DYNAMIC_NETWORKS][CX_SHA256_SIZE] = {0}; +#endif +// Global structure to store the dynamic network information +network_info_t DYNAMIC_NETWORK_INFO[MAX_DYNAMIC_NETWORKS] = {0}; + +/** + * @brief Parse the STRUCTURE_TYPE value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_struct_type(const s_tlv_data *data, s_network_info_ctx *context) { + (void) context; + if (data->length != sizeof(uint8_t)) { + return false; + } + return data->value[0] == TYPE_DYNAMIC_NETWORK; +} + +/** + * @brief Parse the STRUCTURE_VERSION value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_struct_version(const s_tlv_data *data, s_network_info_ctx *context) { + (void) context; + if (data->length != sizeof(uint8_t)) { + return false; + } + return data->value[0] == NETWORK_STRUCT_VERSION; +} + +/** + * @brief Parse the BLOCKCHAIN_FAMILY value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_blockchain_family(const s_tlv_data *data, s_network_info_ctx *context) { + (void) context; + if (data->length != sizeof(uint8_t)) { + return false; + } + return data->value[0] == BLOCKCHAIN_FAMILY_ETHEREUM; +} + +/** + * @brief Parse the CHAIN_ID value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_chain_id(const s_tlv_data *data, s_network_info_ctx *context) { + uint64_t chain_id; + uint8_t buf[sizeof(chain_id)]; + uint64_t max_range; + + (void) context; + if (data->length > sizeof(buf)) { + return false; + } + // Check if the chain ID is supported + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2294.md + max_range = 0x7FFFFFFFFFFFFFDB; + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + chain_id = read_u64_be(buf, 0); + // Check if the chain_id is supported + if ((chain_id > max_range) || (chain_id == 0)) { + PRINTF("Unsupported chain ID: %u\n", chain_id); + return false; + } + context->network.chain_id = chain_id; + return true; +} + +/** + * @brief Parse the NETWORK_NAME value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_name(const s_tlv_data *data, s_network_info_ctx *context) { + (void) context; + if (data->length >= sizeof(context->network.name)) { + return false; + } + // Check if the name is printable + if (!check_name(data->value, data->length)) { + PRINTF("NETWORK_NAME is not printable!\n"); + return false; + } + memcpy(context->network.name, data->value, data->length); + context->network.name[data->length] = '\0'; + return true; +} + +/** + * @brief Parse the NETWORK_TICKER value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_ticker(const s_tlv_data *data, s_network_info_ctx *context) { + (void) context; + if (data->length >= sizeof(context->network.ticker)) { + return false; + } + // Check if the ticker is printable + if (!check_name(data->value, data->length)) { + PRINTF("NETWORK_TICKER is not printable!\n"); + return false; + } + memcpy(context->network.ticker, data->value, data->length); + context->network.ticker[data->length] = '\0'; + return true; +} + +#ifdef HAVE_NBGL +/** + * @brief Parse the NETWORK_ICON_HASH value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_icon_hash(const s_tlv_data *data, s_network_info_ctx *context) { + if (data->length > sizeof(g_network_icon_hash[g_current_network_slot])) { + return false; + } + buf_shrink_expand(data->value, data->length, context->icon_hash, sizeof(context->icon_hash)); + return true; +} +#endif + +/** + * @brief Parse the SIGNATURE value. + * + * @param[in] data data to handle + * @param[out] context struct context + * @return whether the handling was successful + */ +static bool handle_signature(const s_tlv_data *data, s_network_info_ctx *context) { + if (data->length > sizeof(context->signature)) { + return false; + } + context->signature_length = data->length; + memcpy(context->signature, data->value, data->length); + return true; +} + +bool handle_network_info_struct(const s_tlv_data *data, s_network_info_ctx *context) { + bool ret; + + 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_BLOCKCHAIN_FAMILY: + ret = handle_blockchain_family(data, context); + break; + case TAG_CHAIN_ID: + ret = handle_chain_id(data, context); + break; + case TAG_NETWORK_NAME: + ret = handle_name(data, context); + break; + case TAG_TICKER: + ret = handle_ticker(data, context); + break; + case TAG_NETWORK_ICON_HASH: +#ifdef HAVE_NBGL + ret = handle_icon_hash(data, context); +#else + ret = true; +#endif + break; + case TAG_DER_SIGNATURE: + ret = handle_signature(data, context); + break; + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + ret = true; + } + if (ret && (data->tag != TAG_DER_SIGNATURE)) { + hash_nbytes(data->raw, data->raw_size, (cx_hash_t *) &context->hash_ctx); + } + return ret; +} + +/** + * @brief Verify the struct + * + * Verify the SHA-256 hash of the payload against the public key + * + * @param[in] context struct context + * @return whether it was successful + */ +bool verify_network_info_struct(const s_network_info_ctx *context) { + uint8_t hash[INT256_LENGTH]; + + if (cx_hash_no_throw((cx_hash_t *) &context->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH) != + CX_OK) { + return false; + } + + if (check_signature_with_pubkey("Dynamic Network", + hash, + sizeof(hash), + NULL, + 0, +#ifdef HAVE_LEDGER_PKI + CERTIFICATE_PUBLIC_KEY_USAGE_NETWORK, +#endif + (uint8_t *) context->signature, + context->signature_length) != CX_OK) { + return false; + } + + // Check if the chain ID is already registered, if so delete it silently to prevent duplicates + for (int i = 0; i < MAX_DYNAMIC_NETWORKS; ++i) { + if (DYNAMIC_NETWORK_INFO[i].chain_id == context->network.chain_id) { + explicit_bzero(&DYNAMIC_NETWORK_INFO[i], sizeof(DYNAMIC_NETWORK_INFO[i])); + break; + } + } + + // Set the current slot here, because the corresponding icon will be received + // separately, after the network configuration, and should keep the same slot + g_current_network_slot = (g_current_network_slot + 1) % MAX_DYNAMIC_NETWORKS; + + memcpy(&DYNAMIC_NETWORK_INFO[g_current_network_slot], + &context->network, + sizeof(network_info_t)); +#ifdef HAVE_NBGL + memcpy(g_network_icon_hash[g_current_network_slot], + context->icon_hash, + sizeof(context->icon_hash)); +#endif + return true; +} + +#endif // HAVE_DYNAMIC_NETWORKS diff --git a/src_features/provide_network_info/network_info.h b/src_features/provide_network_info/network_info.h new file mode 100644 index 0000000000..713fc5156f --- /dev/null +++ b/src_features/provide_network_info/network_info.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include "network.h" +#include "tlv.h" +#include "signature.h" + +#define MAX_DYNAMIC_NETWORKS 2 // Nb configurations max to store + +// Signature context structure +typedef struct { + network_info_t network; + uint8_t icon_hash[CX_SHA256_SIZE]; + uint8_t signature_length; + uint8_t signature[ECDSA_SIGNATURE_MAX_LENGTH]; + cx_sha256_t hash_ctx; +} s_network_info_ctx; + +#ifdef HAVE_NBGL +extern uint8_t g_network_icon_hash[MAX_DYNAMIC_NETWORKS][CX_SHA256_SIZE]; +#endif +extern network_info_t DYNAMIC_NETWORK_INFO[MAX_DYNAMIC_NETWORKS]; +extern uint8_t g_current_network_slot; + +bool handle_network_info_struct(const s_tlv_data *data, s_network_info_ctx *context); +bool verify_network_info_struct(const s_network_info_ctx *context); diff --git a/src_features/provide_proxy_info/cmd_proxy_info.c b/src_features/provide_proxy_info/cmd_proxy_info.c new file mode 100644 index 0000000000..d0d11def7b --- /dev/null +++ b/src_features/provide_proxy_info/cmd_proxy_info.c @@ -0,0 +1,31 @@ +#if defined(HAVE_EIP712_FULL_SUPPORT) || defined(HAVE_GENERIC_TX_PARSER) + +#include "cmd_proxy_info.h" +#include "proxy_info.h" +#include "tlv_apdu.h" +#include "mem.h" +#include "apdu_constants.h" + +static bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) { + s_proxy_info_ctx ctx = {0}; + + cx_sha256_init(&ctx.struct_hash); + if (!tlv_parse(payload, size, (f_tlv_data_handler) &handle_proxy_info_struct, &ctx)) { + return false; + } + if (to_free) mem_dealloc(sizeof(size)); + if (!verify_proxy_info_struct(&ctx)) { + return false; + } + return true; +} + +uint16_t handle_proxy_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload) { + (void) p2; + if (!tlv_from_apdu(p1 == P1_FIRST_CHUNK, lc, payload, &handle_tlv_payload)) { + return APDU_RESPONSE_INVALID_DATA; + } + return APDU_RESPONSE_OK; +} + +#endif diff --git a/src_features/provide_proxy_info/cmd_proxy_info.h b/src_features/provide_proxy_info/cmd_proxy_info.h new file mode 100644 index 0000000000..02e45135b4 --- /dev/null +++ b/src_features/provide_proxy_info/cmd_proxy_info.h @@ -0,0 +1,13 @@ +#if defined(HAVE_EIP712_FULL_SUPPORT) || defined(HAVE_GENERIC_TX_PARSER) + +#ifndef CMD_PROXY_INFO_H_ +#define CMD_PROXY_INFO_H_ + +#include +#include + +uint16_t handle_proxy_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload); + +#endif // CMD_PROXY_INFO_H_ + +#endif diff --git a/src_features/provide_proxy_info/proxy_info.c b/src_features/provide_proxy_info/proxy_info.c new file mode 100644 index 0000000000..1b1cbe8b9b --- /dev/null +++ b/src_features/provide_proxy_info/proxy_info.c @@ -0,0 +1,245 @@ +#if defined(HAVE_EIP712_FULL_SUPPORT) || defined(HAVE_GENERIC_TX_PARSER) + +#include "proxy_info.h" +#include "read.h" +#include "utils.h" // buf_shrink_expand +#include "challenge.h" +#include "public_keys.h" + +enum { + TAG_STRUCT_TYPE = 0x01, + TAG_STRUCT_VERSION = 0x02, + TAG_CHALLENGE = 0x012, + TAG_ADDRESS = 0x22, + TAG_CHAIN_ID = 0x23, + TAG_SELECTOR = 0x28, + TAG_IMPLEM_ADDRESS = 0x29, + TAG_SIGNATURE = 0x15, +}; + +#define TYPE_PROXY_INFO 0x26 + +static s_proxy_info g_proxy_info = {0}; + +static bool handle_type(const s_tlv_data *data, s_proxy_info_ctx *context) { + (void) context; + + if (data->length != sizeof(uint8_t)) { + return false; + } + return data->value[0] == TYPE_PROXY_INFO; +} + +static bool handle_version(const s_tlv_data *data, s_proxy_info_ctx *context) { + if (data->length != sizeof(context->version)) { + return false; + } + context->version = data->value[0]; + return true; +} + +static bool handle_challenge(const s_tlv_data *data, s_proxy_info_ctx *context) { + uint8_t buf[sizeof(context->challenge)]; + + if (data->length > sizeof(buf)) { + return false; + } + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->challenge = read_u32_be(buf, 0); + return true; +} + +static bool handle_address(const s_tlv_data *data, s_proxy_info_ctx *context) { + if (data->length > sizeof(context->proxy_info.address)) { + return false; + } + buf_shrink_expand(data->value, + data->length, + context->proxy_info.address, + sizeof(context->proxy_info.address)); + return true; +} + +static bool handle_chain_id(const s_tlv_data *data, s_proxy_info_ctx *context) { + uint8_t buf[sizeof(context->proxy_info.chain_id)]; + + if (data->length > sizeof(buf)) { + return false; + } + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->proxy_info.chain_id = read_u64_be(buf, 0); + return true; +} + +static bool handle_selector(const s_tlv_data *data, s_proxy_info_ctx *context) { + if (data->length > sizeof(context->proxy_info.selector)) { + return false; + } + buf_shrink_expand(data->value, + data->length, + context->proxy_info.selector, + sizeof(context->proxy_info.selector)); + context->proxy_info.has_selector = true; + return true; +} + +static bool handle_implem_address(const s_tlv_data *data, s_proxy_info_ctx *context) { + if (data->length > sizeof(context->proxy_info.implem_address)) { + return false; + } + buf_shrink_expand(data->value, + data->length, + context->proxy_info.implem_address, + sizeof(context->proxy_info.implem_address)); + return true; +} + +static bool handle_signature(const s_tlv_data *data, s_proxy_info_ctx *context) { + if (data->length > sizeof(context->signature)) { + return false; + } + context->signature_length = data->length; + memcpy(context->signature, data->value, data->length); + return true; +} + +bool handle_proxy_info_struct(const s_tlv_data *data, s_proxy_info_ctx *context) { + bool ret; + + switch (data->tag) { + case TAG_STRUCT_TYPE: + ret = handle_type(data, context); + break; + case TAG_STRUCT_VERSION: + ret = handle_version(data, context); + break; + case TAG_CHALLENGE: + ret = handle_challenge(data, context); + break; + case TAG_ADDRESS: + ret = handle_address(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_IMPLEM_ADDRESS: + ret = handle_implem_address(data, context); + break; + case TAG_SIGNATURE: + ret = handle_signature(data, context); + break; + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + ret = false; + } + if (ret && (data->tag != TAG_SIGNATURE)) { + if (cx_hash_no_throw((cx_hash_t *) &context->struct_hash, + 0, + data->raw, + data->raw_size, + NULL, + 0) != CX_OK) { + return false; + } + } + return ret; +} + +bool verify_proxy_info_struct(const s_proxy_info_ctx *context) { + uint8_t hash[INT256_LENGTH]; + uint32_t challenge; + + if (cx_hash_no_throw((cx_hash_t *) &context->struct_hash, + CX_LAST, + NULL, + 0, + hash, + sizeof(hash)) != CX_OK) { + PRINTF("Error: could not finalize struct hash!\n"); + return false; + } + challenge = get_challenge(); + roll_challenge(); + if (context->challenge != challenge) { + PRINTF("Error: challenge mismatch!\n"); + return false; + } + if (check_signature_with_pubkey("proxy info", + hash, + sizeof(hash), + NULL, + 0, +#ifdef HAVE_LEDGER_PKI + CERTIFICATE_PUBLIC_KEY_USAGE_CALLDATA, +#endif + (uint8_t *) context->signature, + context->signature_length) != CX_OK) { + PRINTF("Error: signature verification failed!\n"); + return false; + } + memcpy(&g_proxy_info, &context->proxy_info, sizeof(g_proxy_info)); + PRINTF("================== PROXY INFO ====================\n"); + PRINTF("chain ID = %u\n", (uint32_t) g_proxy_info.chain_id); + PRINTF("address = 0x%.*h\n", sizeof(g_proxy_info.address), g_proxy_info.address); + PRINTF("implementation address = 0x%.*h\n", + sizeof(g_proxy_info.implem_address), + g_proxy_info.implem_address); + if (g_proxy_info.has_selector) { + PRINTF("selector = 0x%.*h\n", sizeof(g_proxy_info.selector), g_proxy_info.selector); + } + PRINTF("==================================================\n"); + return true; +} + +static bool check_proxy_params(const uint64_t *chain_id, + const uint8_t *addr, + const uint8_t *selector, + const uint64_t *ref_chain_id, + const uint8_t *ref_addr, + const uint8_t *ref_selector) { + if ((chain_id == NULL) || (*chain_id != *ref_chain_id)) { + return false; + } + if (memcmp(addr, ref_addr, ADDRESS_LENGTH) != 0) { + return false; + } + if (selector != NULL) { + if (memcmp(selector, ref_selector, CALLDATA_SELECTOR_SIZE) != 0) { + return false; + } + } + return true; +} + +const uint8_t *get_proxy_contract(const uint64_t *chain_id, + const uint8_t *addr, + const uint8_t *selector) { + if (!check_proxy_params(chain_id, + addr, + selector, + &g_proxy_info.chain_id, + g_proxy_info.implem_address, + g_proxy_info.selector)) { + return NULL; + } + return g_proxy_info.address; +} + +const uint8_t *get_implem_contract(const uint64_t *chain_id, + const uint8_t *addr, + const uint8_t *selector) { + if (!check_proxy_params(chain_id, + addr, + selector, + &g_proxy_info.chain_id, + g_proxy_info.address, + g_proxy_info.selector)) { + return NULL; + } + return g_proxy_info.implem_address; +} + +#endif diff --git a/src_features/provide_proxy_info/proxy_info.h b/src_features/provide_proxy_info/proxy_info.h new file mode 100644 index 0000000000..eff788a88e --- /dev/null +++ b/src_features/provide_proxy_info/proxy_info.h @@ -0,0 +1,42 @@ +#if defined(HAVE_EIP712_FULL_SUPPORT) || defined(HAVE_GENERIC_TX_PARSER) + +#ifndef PROXY_INFO_H_ +#define PROXY_INFO_H_ + +#include +#include +#include "cx.h" +#include "tlv.h" +#include "common_utils.h" // ADDRESS_LENGTH +#include "calldata.h" // CALLDATA_SELECTOR_SIZE +#include "signature.h" + +typedef struct { + uint64_t chain_id; + uint8_t address[ADDRESS_LENGTH]; + bool has_selector; + uint8_t selector[CALLDATA_SELECTOR_SIZE]; + uint8_t implem_address[ADDRESS_LENGTH]; +} s_proxy_info; + +typedef struct { + uint8_t version; + uint32_t challenge; + s_proxy_info proxy_info; + uint8_t signature_length; + uint8_t signature[ECDSA_SIGNATURE_MAX_LENGTH]; + cx_sha256_t struct_hash; +} s_proxy_info_ctx; + +bool handle_proxy_info_struct(const s_tlv_data *data, s_proxy_info_ctx *context); +bool verify_proxy_info_struct(const s_proxy_info_ctx *context); +const uint8_t *get_proxy_contract(const uint64_t *chain_id, + const uint8_t *addr, + const uint8_t *selector); +const uint8_t *get_implem_contract(const uint64_t *chain_id, + const uint8_t *addr, + const uint8_t *selector); + +#endif // PROXY_INFO_H_ + +#endif diff --git a/src_features/provide_trusted_name/cmd_trusted_name.c b/src_features/provide_trusted_name/cmd_trusted_name.c new file mode 100644 index 0000000000..dcb1b2f43f --- /dev/null +++ b/src_features/provide_trusted_name/cmd_trusted_name.c @@ -0,0 +1,42 @@ +#ifdef HAVE_TRUSTED_NAME + +#include +#include "cmd_trusted_name.h" +#include "trusted_name.h" +#include "mem.h" +#include "challenge.h" +#include "tlv_apdu.h" +#include "apdu_constants.h" + +static bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) { + s_trusted_name_ctx ctx = {0}; + bool parsing_success; + + ctx.trusted_name.name = g_trusted_name; + cx_sha256_init(&ctx.hash_ctx); + parsing_success = + tlv_parse(payload, size, (f_tlv_data_handler) &handle_trusted_name_struct, &ctx); + if (to_free) mem_dealloc(size); + if (!parsing_success || !verify_trusted_name_struct(&ctx)) { + roll_challenge(); // prevent brute-force guesses + return false; + } + roll_challenge(); // prevent replays + return true; +} + +/** + * Handle trusted name APDU + * + * @param[in] p1 first APDU instruction parameter + * @param[in] data APDU payload + * @param[in] length payload size + */ +uint16_t handle_trusted_name(uint8_t p1, const uint8_t *data, uint8_t length) { + if (!tlv_from_apdu(p1 == P1_FIRST_CHUNK, length, data, &handle_tlv_payload)) { + return APDU_RESPONSE_INVALID_DATA; + } + return APDU_RESPONSE_OK; +} + +#endif // HAVE_TRUSTED_NAME diff --git a/src_features/provide_trusted_name/cmd_trusted_name.h b/src_features/provide_trusted_name/cmd_trusted_name.h new file mode 100644 index 0000000000..454564a975 --- /dev/null +++ b/src_features/provide_trusted_name/cmd_trusted_name.h @@ -0,0 +1,12 @@ +#ifdef HAVE_TRUSTED_NAME + +#ifndef CMD_TRUSTED_NAME_H_ +#define CMD_TRUSTED_NAME_H_ + +#include + +uint16_t handle_trusted_name(uint8_t p1, const uint8_t *data, uint8_t length); + +#endif // !CMD_TRUSTED_NAME_H_ + +#endif // !HAVE_TRUSTED_NAME diff --git a/src_features/provide_trusted_name/trusted_name.c b/src_features/provide_trusted_name/trusted_name.c new file mode 100644 index 0000000000..8e453fe8a3 --- /dev/null +++ b/src_features/provide_trusted_name/trusted_name.c @@ -0,0 +1,644 @@ +#ifdef HAVE_TRUSTED_NAME + +#include +#include "trusted_name.h" +#include "network.h" // chain_is_ethereum_compatible +#include "utils.h" // SET_BIT +#include "read.h" +#include "challenge.h" +#include "hash_bytes.h" +#include "public_keys.h" +#include "proxy_info.h" + +typedef enum { STRUCT_TYPE_TRUSTED_NAME = 0x03 } e_struct_type; + +typedef enum { SIG_ALGO_SECP256K1 = 0x01 } e_sig_algo; + +typedef enum { + SLIP_44_ETHEREUM = 60, +} e_coin_type; + +// This enum needs to be ordered the same way as the e_tlv_tag one ! +typedef enum { + STRUCT_TYPE_RCV_BIT = 0, + STRUCT_VERSION_RCV_BIT, + NOT_VALID_AFTER_RCV_BIT, + CHALLENGE_RCV_BIT, + SIGNER_KEY_ID_RCV_BIT, + SIGNER_ALGO_RCV_BIT, + SIGNATURE_RCV_BIT, + TRUSTED_NAME_RCV_BIT, + COIN_TYPE_RCV_BIT, + ADDRESS_RCV_BIT, + CHAIN_ID_RCV_BIT, + TRUSTED_NAME_TYPE_RCV_BIT, + TRUSTED_NAME_SOURCE_RCV_BIT, + NFT_ID_RCV_BIT, +} e_tlv_rcv_bit; + +typedef enum { + STRUCT_TYPE = 0x01, + STRUCT_VERSION = 0x02, + NOT_VALID_AFTER = 0x10, + CHALLENGE = 0x12, + SIGNER_KEY_ID = 0x13, + SIGNER_ALGO = 0x14, + SIGNATURE = 0x15, + TRUSTED_NAME = 0x20, + COIN_TYPE = 0x21, + ADDRESS = 0x22, + CHAIN_ID = 0x23, + TRUSTED_NAME_TYPE = 0x70, + TRUSTED_NAME_SOURCE = 0x71, + NFT_ID = 0x72, +} e_tlv_tag; + +static s_trusted_name_info g_trusted_name_info = {0}; +char g_trusted_name[TRUSTED_NAME_MAX_LENGTH + 1]; + +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; + } + return false; +} + +static bool matching_source(e_name_source source, + uint8_t source_count, + const e_name_source *sources) { + for (int i = 0; i < source_count; ++i) { + if (source == sources[i]) return true; + } + return false; +} + +static bool matching_trusted_name(const s_trusted_name_info *trusted_name, + uint8_t type_count, + const e_name_type *types, + uint8_t source_count, + const e_name_source *sources, + const uint64_t *chain_id, + const uint8_t *addr) { + const uint8_t *tmp; + + switch (trusted_name->struct_version) { + case 1: + if (!matching_type(TN_TYPE_ACCOUNT, type_count, types)) { + return false; + } + if (!chain_is_ethereum_compatible(chain_id)) { + return false; + } + break; + case 2: + if (!matching_type(trusted_name->name_type, type_count, types)) { + return false; + } + if (!matching_source(trusted_name->name_source, source_count, sources)) { + return false; + } + if (*chain_id != trusted_name->chain_id) { + return false; + } + + if (trusted_name->name_type == TN_TYPE_CONTRACT) { + if ((tmp = get_implem_contract(chain_id, addr, NULL)) != NULL) { + addr = tmp; + } + } + break; + } + return memcmp(addr, trusted_name->addr, ADDRESS_LENGTH) == 0; +} + +/** + * Checks if a trusted name matches the given parameters + * + * Always wipes the content of \ref g_trusted_name_info + * + * @param[in] types_count number of given trusted name types + * @param[in] types given trusted name types + * @param[in] chain_id given chain ID + * @param[in] addr given address + * @return whether there is or not + */ +const char *get_trusted_name(uint8_t type_count, + const e_name_type *types, + uint8_t source_count, + const e_name_source *sources, + const uint64_t *chain_id, + const uint8_t *addr) { + const char *ret = NULL; + + if (matching_trusted_name(&g_trusted_name_info, + type_count, + types, + source_count, + sources, + chain_id, + addr)) { + ret = g_trusted_name_info.name; + } + explicit_bzero(&g_trusted_name_info, sizeof(g_trusted_name_info)); + return ret; +} + +/** + * Handler for tag \ref STRUCT_TYPE + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_struct_type(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length != sizeof(e_struct_type)) { + return false; + } + context->rcv_flags |= SET_BIT(STRUCT_TYPE_RCV_BIT); + return (data->value[0] == STRUCT_TYPE_TRUSTED_NAME); +} + +/** + * Handler for tag \ref NOT_VALID_AFTER + * + * @param[in] data the tlv data + * @param[] context the trusted name context + * @return whether it was successful + */ +static bool handle_not_valid_after(const s_tlv_data *data, s_trusted_name_ctx *context) { + const uint8_t app_version[] = {MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION}; + + (void) context; + if (data->length != ARRAYLEN(app_version)) { + return false; + } + for (int i = 0; i < (int) ARRAYLEN(app_version); ++i) { + if (data->value[i] < app_version[i]) { + PRINTF("Expired trusted name : %u.%u.%u < %u.%u.%u\n", + data->value[0], + data->value[1], + data->value[2], + app_version[0], + app_version[1], + app_version[2]); + return false; + } + } + return true; +} + +/** + * Handler for tag \ref STRUCT_VERSION + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_struct_version(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length != sizeof(context->trusted_name.struct_version)) { + return false; + } + context->trusted_name.struct_version = data->value[0]; + context->rcv_flags |= SET_BIT(STRUCT_VERSION_RCV_BIT); + return true; +} + +/** + * Handler for tag \ref CHALLENGE + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_challenge(const s_tlv_data *data, s_trusted_name_ctx *context) { + uint8_t buf[sizeof(uint32_t)]; + + if (data->length > sizeof(buf)) { + return false; + } + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->rcv_flags |= SET_BIT(CHALLENGE_RCV_BIT); + return (read_u32_be(buf, 0) == get_challenge()); +} + +/** + * Handler for tag \ref SIGNER_KEY_ID + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_sign_key_id(const s_tlv_data *data, s_trusted_name_ctx *context) { + // for some reason this is sent as 2 bytes + uint16_t value; + uint8_t buf[sizeof(value)]; + + if (data->length > sizeof(buf)) { + return false; + } + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + value = read_u16_be(buf, 0); + if (value > UINT8_MAX) { + return false; + } + context->key_id = value; + context->rcv_flags |= SET_BIT(SIGNER_KEY_ID_RCV_BIT); + return true; +} + +/** + * Handler for tag \ref SIGNER_ALGO + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_sign_algo(const s_tlv_data *data, s_trusted_name_ctx *context) { + // for some reason this is sent as 2 bytes + uint8_t buf[sizeof(uint16_t)]; + + if (data->length > sizeof(buf)) { + return false; + } + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->rcv_flags |= SET_BIT(SIGNER_ALGO_RCV_BIT); + return (read_u16_be(buf, 0) == SIG_ALGO_SECP256K1); +} + +/** + * Handler for tag \ref SIGNATURE + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_signature(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length > sizeof(context->input_sig)) { + return false; + } + context->input_sig_size = data->length; + memcpy(context->input_sig, data->value, data->length); + context->rcv_flags |= SET_BIT(SIGNATURE_RCV_BIT); + return true; +} + +/** + * Tests if the given account name character is valid (in our subset of allowed characters) + * + * @param[in] c given character + * @return whether the character is valid + */ +static bool is_valid_account_character(char c) { + if (isalpha((int) c)) { + if (!islower((int) c)) { + return false; + } + } else if (!isdigit((int) c)) { + switch (c) { + case '.': + case '-': + case '_': + break; + default: + return false; + } + } + return true; +} + +/** + * Handler for tag \ref TRUSTED_NAME + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_trusted_name(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length > TRUSTED_NAME_MAX_LENGTH) { + PRINTF("Domain name too long! (%u)\n", data->length); + return false; + } + if ((context->trusted_name.struct_version == 1) || + (context->trusted_name.name_type == TN_TYPE_ACCOUNT)) { + // TODO: Remove once other domain name providers are supported + if ((data->length < 5) || + (strncmp(".eth", (char *) &data->value[data->length - 4], 4) != 0)) { + PRINTF("Unexpected TLD!\n"); + return false; + } + for (int idx = 0; idx < data->length; ++idx) { + if (!is_valid_account_character(data->value[idx])) { + PRINTF("Domain name contains non-allowed character! (0x%x)\n", data->value[idx]); + return false; + } + context->trusted_name.name[idx] = data->value[idx]; + } + } else { + memcpy(context->trusted_name.name, data->value, data->length); + } + context->trusted_name.name[data->length] = '\0'; + context->rcv_flags |= SET_BIT(TRUSTED_NAME_RCV_BIT); + return true; +} + +/** + * Handler for tag \ref COIN_TYPE + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_coin_type(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length != sizeof(e_coin_type)) { + return false; + } + context->rcv_flags |= SET_BIT(COIN_TYPE_RCV_BIT); + return (data->value[0] == SLIP_44_ETHEREUM); +} + +/** + * Handler for tag \ref ADDRESS + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_address(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length != ADDRESS_LENGTH) { + return false; + } + memcpy(context->trusted_name.addr, data->value, ADDRESS_LENGTH); + context->rcv_flags |= SET_BIT(ADDRESS_RCV_BIT); + return true; +} + +/** + * Handler for tag \ref CHAIN_ID + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_chain_id(const s_tlv_data *data, s_trusted_name_ctx *context) { + context->trusted_name.chain_id = u64_from_BE(data->value, data->length); + context->rcv_flags |= SET_BIT(CHAIN_ID_RCV_BIT); + return true; +} + +/** + * Handler for tag \ref TRUSTED_NAME_TYPE + * + * @param[in] data the tlv data + * @param[in,out] context the trusted name context + * @return whether it was successful + */ +static bool handle_trusted_name_type(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length != sizeof(e_name_type)) { + return false; + } + context->trusted_name.name_type = data->value[0]; + switch (context->trusted_name.name_type) { + case TN_TYPE_ACCOUNT: + case TN_TYPE_CONTRACT: + break; + case TN_TYPE_NFT_COLLECTION: + case TN_TYPE_TOKEN: + case TN_TYPE_WALLET: + case TN_TYPE_CONTEXT_ADDRESS: + default: + PRINTF("Error: unsupported trusted name type (%u)!\n", context->trusted_name.name_type); + return false; + } + context->rcv_flags |= SET_BIT(TRUSTED_NAME_TYPE_RCV_BIT); + return true; +} + +/** + * Handler for tag \ref TRUSTED_NAME_SOURCE + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_trusted_name_source(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length != sizeof(e_name_source)) { + return false; + } + context->trusted_name.name_source = data->value[0]; + switch (context->trusted_name.name_source) { + case TN_SOURCE_CAL: + case TN_SOURCE_ENS: + break; + case TN_SOURCE_LAB: + case TN_SOURCE_UD: + case TN_SOURCE_FN: + case TN_SOURCE_DNS: + case TN_SOURCE_DYNAMIC_RESOLVER: + default: + PRINTF("Error: unsupported trusted name source (%u)!\n", + context->trusted_name.name_source); + return false; + } + context->rcv_flags |= SET_BIT(TRUSTED_NAME_SOURCE_RCV_BIT); + return true; +} + +#ifdef HAVE_NFT_SUPPORT +/** + * Handler for tag \ref NFT_ID + * + * @param[in] data the tlv data + * @param[out] context the trusted name context + * @return whether it was successful + */ +static bool handle_nft_id(const s_tlv_data *data, s_trusted_name_ctx *context) { + if (data->length > sizeof(context->trusted_name.nft_id)) { + return false; + } + buf_shrink_expand(data->value, + data->length, + context->trusted_name.nft_id, + sizeof(context->trusted_name.nft_id)); + context->rcv_flags |= SET_BIT(NFT_ID_RCV_BIT); + return true; // unhandled for now +} +#endif + +bool handle_trusted_name_struct(const s_tlv_data *data, s_trusted_name_ctx *context) { + bool ret; + + (void) context; + switch (data->tag) { + case STRUCT_TYPE: + ret = handle_struct_type(data, context); + break; + case STRUCT_VERSION: + ret = handle_struct_version(data, context); + break; + case NOT_VALID_AFTER: + ret = handle_not_valid_after(data, context); + break; + case CHALLENGE: + ret = handle_challenge(data, context); + break; + case SIGNER_KEY_ID: + ret = handle_sign_key_id(data, context); + break; + case SIGNER_ALGO: + ret = handle_sign_algo(data, context); + break; + case SIGNATURE: + ret = handle_signature(data, context); + break; + case TRUSTED_NAME: + ret = handle_trusted_name(data, context); + break; + case COIN_TYPE: + ret = handle_coin_type(data, context); + break; + case ADDRESS: + ret = handle_address(data, context); + break; + case CHAIN_ID: + ret = handle_chain_id(data, context); + break; + case TRUSTED_NAME_TYPE: + ret = handle_trusted_name_type(data, context); + break; + case TRUSTED_NAME_SOURCE: + ret = handle_trusted_name_source(data, context); + break; +#ifdef HAVE_NFT_SUPPORT + case NFT_ID: + ret = handle_nft_id(data, context); + break; +#endif + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + ret = false; + } + if (ret && (data->tag != SIGNATURE)) { + hash_nbytes(data->raw, data->raw_size, (cx_hash_t *) &context->hash_ctx); + } + return ret; +} + +/** + * Verify the signature context + * + * Verify the SHA-256 hash of the payload against the public key + * + * @param[in] context the trusted name context + * @return whether it was successful + */ +static bool verify_trusted_name_signature(const s_trusted_name_ctx *context) { + uint8_t hash[INT256_LENGTH]; + const uint8_t *pk; + size_t pk_size; + + switch (context->key_id) { + case TN_KEY_ID_DOMAIN_SVC: + pk = TRUSTED_NAME_PUB_KEY; + pk_size = sizeof(TRUSTED_NAME_PUB_KEY); + break; + case TN_KEY_ID_CAL: + pk = LEDGER_SIGNATURE_PUBLIC_KEY; + pk_size = sizeof(LEDGER_SIGNATURE_PUBLIC_KEY); + break; + default: + PRINTF("Error: Unknown metadata key ID %u\n", context->key_id); + return false; + } + + if (cx_hash_no_throw((cx_hash_t *) &context->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH) != + CX_OK) { + return false; + } + + if (check_signature_with_pubkey("Trusted Name", + hash, + sizeof(hash), + pk, + pk_size, +#ifdef HAVE_LEDGER_PKI + CERTIFICATE_PUBLIC_KEY_USAGE_TRUSTED_NAME, +#endif + (uint8_t *) (context->input_sig), + context->input_sig_size) != CX_OK) { + return false; + } + return true; +} + +/** + * Verify the validity of the received trusted struct + * + * @param[in] context the trusted name context + * @return whether the struct is valid + */ +bool verify_trusted_name_struct(const s_trusted_name_ctx *context) { + uint32_t required_flags; + + if (!(SET_BIT(STRUCT_VERSION_RCV_BIT) & context->rcv_flags)) { + PRINTF("Error: no struct version specified!\n"); + return false; + } + required_flags = SET_BIT(STRUCT_TYPE_RCV_BIT) | SET_BIT(STRUCT_VERSION_RCV_BIT) | + SET_BIT(SIGNER_KEY_ID_RCV_BIT) | SET_BIT(SIGNER_ALGO_RCV_BIT) | + SET_BIT(SIGNATURE_RCV_BIT) | SET_BIT(TRUSTED_NAME_RCV_BIT) | + SET_BIT(ADDRESS_RCV_BIT); + switch (context->trusted_name.struct_version) { + case 1: + required_flags |= SET_BIT(CHALLENGE_RCV_BIT) | SET_BIT(COIN_TYPE_RCV_BIT); + if ((context->rcv_flags & required_flags) != required_flags) { + return false; + } + break; + case 2: + required_flags |= SET_BIT(CHAIN_ID_RCV_BIT) | SET_BIT(TRUSTED_NAME_TYPE_RCV_BIT) | + SET_BIT(TRUSTED_NAME_SOURCE_RCV_BIT); + if ((context->rcv_flags & required_flags) != required_flags) { + return false; + } + switch (context->trusted_name.name_type) { + case TN_TYPE_ACCOUNT: + if (context->trusted_name.name_source == TN_SOURCE_CAL) { + PRINTF("Error: cannot accept an account name from the CAL!\n"); + return false; + } + if (!(context->rcv_flags & SET_BIT(CHALLENGE_RCV_BIT))) { + PRINTF("Error: trusted account name requires a challenge!\n"); + return false; + } + break; + case TN_TYPE_CONTRACT: + if (context->trusted_name.name_source != TN_SOURCE_CAL) { + PRINTF("Error: cannot accept a contract name from given source (%u)!\n", + context->trusted_name.name_source); + return false; + } + break; + default: + return false; + } + break; + default: + PRINTF("Error: unsupported trusted name struct version (%u) !\n", + context->trusted_name.struct_version); + return false; + } + + if (!verify_trusted_name_signature(context)) { + return false; + } + + memcpy(&g_trusted_name_info, &context->trusted_name, sizeof(g_trusted_name_info)); + + PRINTF("Registered : %s => %.*h\n", + g_trusted_name_info.name, + ADDRESS_LENGTH, + g_trusted_name_info.addr); + return true; +} + +#endif // HAVE_TRUSTED_NAME diff --git a/src_features/provideTrustedName/trusted_name.h b/src_features/provide_trusted_name/trusted_name.h similarity index 53% rename from src_features/provideTrustedName/trusted_name.h rename to src_features/provide_trusted_name/trusted_name.h index ad7d05a7d1..a6df693da2 100644 --- a/src_features/provideTrustedName/trusted_name.h +++ b/src_features/provide_trusted_name/trusted_name.h @@ -5,6 +5,9 @@ #include #include +#include "common_utils.h" // ADDRESS_LENGTH +#include "tlv.h" +#include "signature.h" #define TRUSTED_NAME_MAX_LENGTH 30 @@ -32,16 +35,42 @@ typedef enum { TN_SOURCE_COUNT, } e_name_source; +typedef enum { TN_KEY_ID_DOMAIN_SVC = 0x07, TN_KEY_ID_CAL = 0x09 } e_tn_key_id; + +typedef struct { + bool valid; + uint8_t struct_version; + char *name; + uint8_t addr[ADDRESS_LENGTH]; + uint64_t chain_id; + e_name_type name_type; + e_name_source name_source; +#ifdef HAVE_NFT_SUPPORT + uint8_t nft_id[INT256_LENGTH]; +#endif +} s_trusted_name_info; + +typedef struct { + s_trusted_name_info trusted_name; + e_tn_key_id key_id; + uint8_t input_sig_size; + uint8_t input_sig[ECDSA_SIGNATURE_MAX_LENGTH]; + cx_sha256_t hash_ctx; + uint32_t rcv_flags; +} s_trusted_name_ctx; + const char *get_trusted_name(uint8_t type_count, const e_name_type *types, uint8_t source_count, const e_name_source *sources, const uint64_t *chain_id, const uint8_t *addr); -uint16_t handle_provide_trusted_name(uint8_t p1, const uint8_t *data, uint8_t length); extern char g_trusted_name[TRUSTED_NAME_MAX_LENGTH + 1]; -#endif // TRUSTED_NAME_H_ +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); + +#endif // !TRUSTED_NAME_H_ -#endif // HAVE_TRUSTED_NAME +#endif // !HAVE_TRUSTED_NAME diff --git a/src_features/provide_tx_simulation/cmd_get_tx_simulation.c b/src_features/provide_tx_simulation/cmd_get_tx_simulation.c new file mode 100644 index 0000000000..0b7ae9fc9a --- /dev/null +++ b/src_features/provide_tx_simulation/cmd_get_tx_simulation.c @@ -0,0 +1,821 @@ +#ifdef HAVE_WEB3_CHECKS + +#include "cmd_get_tx_simulation.h" +#include "apdu_constants.h" +#include "hash_bytes.h" +#include "public_keys.h" +#include "feature_signTx.h" +#include "tlv.h" +#include "tlv_apdu.h" +#include "mem.h" +#include "utils.h" +#include "nbgl_use_case.h" +#ifdef HAVE_LEDGER_PKI +#include "os_pki.h" +#endif +#include "network.h" +#include "ui_callbacks.h" + +#define TYPE_TX_SIMULATION 0x09 +#define STRUCT_VERSION 0x01 + +enum { + CATEGORY_OTHERS = 0x01, + CATEGORY_ADDRESS = 0x02, + CATEGORY_DAPP = 0x03, + CATEGORY_LOSING_OPERATION = 0x04, +}; + +enum { + TAG_STRUCTURE_TYPE = 0x01, + TAG_STRUCTURE_VERSION = 0x02, + TAG_ADDRESS = 0x22, + TAG_CHAIN_ID = 0x23, + TAG_TX_HASH = 0x27, + TAG_DOMAIN_HASH = 0x28, + TAG_W3C_NORMALIZED_RISK = 0x80, + TAG_W3C_NORMALIZED_CATEGORY = 0x81, + TAG_W3C_PROVIDER_MSG = 0x82, + TAG_W3C_TINY_URL = 0x83, + TAG_W3C_SIMU_TYPE = 0x84, + TAG_DER_SIGNATURE = 0x15, +}; + +enum { + BIT_STRUCTURE_TYPE, + BIT_STRUCTURE_VERSION, + BIT_ADDRESS, + BIT_CHAIN_ID, + BIT_TX_HASH, + BIT_DOMAIN_HASH, + BIT_W3C_NORMALIZED_RISK, + BIT_W3C_NORMALIZED_CATEGORY, + BIT_W3C_PROVIDER_MSG, + BIT_W3C_TINY_URL, + BIT_W3C_SIMU_TYPE, + BIT_DER_SIGNATURE, +}; + +typedef struct { + tx_simulation_t *simu; + uint8_t sig_size; + uint8_t *sig; + cx_sha256_t hash_ctx; + uint32_t rcv_flags; +} s_tx_simu_ctx; + +// Global structure to store the tx simultion parameters +tx_simulation_t TX_SIMULATION = {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 APDU_RESPONSE_INVALID_DATA; \ + } \ + } while (0) +#define CHECK_FIELD_OVERFLOW(tag, field, len) \ + do { \ + if (len >= sizeof(field)) { \ + PRINTF("%s Size overflow!\n", tag); \ + return APDU_RESPONSE_INSUFFICIENT_MEMORY; \ + } \ + } 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 APDU_RESPONSE_INVALID_DATA; \ + } \ + } while (0) + +// Macro to check the field value +#define CHECK_EMPTY_BUFFER(tag, field, len) \ + do { \ + if (memcmp(field, empty, len) == 0) { \ + PRINTF("%s Zero buffer!\n", tag); \ + return APDU_RESPONSE_INVALID_DATA; \ + } \ + } while (0) + +// Macro to copy the field +#define COPY_FIELD(field, data) \ + do { \ + memmove((void *) field, data->value, data->length); \ + } while (0) + +/** + * @brief Parse the STRUCTURE_TYPE value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_struct_type(const s_tlv_data *data, s_tx_simu_ctx *context) { + CHECK_FIELD_LENGTH("STRUCTURE_TYPE", data->length, 1); + CHECK_FIELD_VALUE("STRUCTURE_TYPE", data->value[0], TYPE_TX_SIMULATION); + context->rcv_flags |= SET_BIT(BIT_STRUCTURE_TYPE); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the STRUCTURE_VERSION value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_struct_version(const s_tlv_data *data, s_tx_simu_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 APDU_RESPONSE_OK; +} + +/** + * @brief Parse the TX_HASH value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_tx_hash(const s_tlv_data *data, s_tx_simu_ctx *context) { + uint8_t empty[HASH_SIZE] = {0}; + CHECK_FIELD_LENGTH("TX_HASH", data->length, HASH_SIZE); + CHECK_EMPTY_BUFFER("TX_HASH", data->value, data->length); + COPY_FIELD(context->simu->tx_hash, data); + context->rcv_flags |= SET_BIT(BIT_TX_HASH); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the DOMAIN_HASH value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_domain_hash(const s_tlv_data *data, s_tx_simu_ctx *context) { + uint8_t empty[HASH_SIZE] = {0}; + CHECK_FIELD_LENGTH("DOMAIN_HASH", data->length, HASH_SIZE); + CHECK_EMPTY_BUFFER("DOMAIN_HASH", data->value, data->length); + COPY_FIELD(context->simu->domain_hash, data); + context->rcv_flags |= SET_BIT(BIT_DOMAIN_HASH); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the ADDRESS value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_address(const s_tlv_data *data, s_tx_simu_ctx *context) { + uint8_t empty[ADDRESS_LENGTH] = {0}; + CHECK_FIELD_LENGTH("ADDRESS", data->length, ADDRESS_LENGTH); + CHECK_EMPTY_BUFFER("ADDRESS", data->value, data->length); + COPY_FIELD(context->simu->addr, data); + context->rcv_flags |= SET_BIT(BIT_ADDRESS); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the CHAIN_ID value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_chain_id(const s_tlv_data *data, s_tx_simu_ctx *context) { + uint64_t chain_id; + uint64_t max_range; + + CHECK_FIELD_LENGTH("CHAIN_ID", data->length, sizeof(uint64_t)); + // Check if the chain ID is supported + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2294.md + max_range = 0x7FFFFFFFFFFFFFDB; + chain_id = u64_from_BE(data->value, data->length); + // Check if the chain_id is supported + if ((chain_id > max_range) || (chain_id == 0)) { + PRINTF("Unsupported chain ID: %u\n", chain_id); + return APDU_RESPONSE_INVALID_DATA; + } + + context->simu->chain_id = chain_id; + context->rcv_flags |= SET_BIT(BIT_CHAIN_ID); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the W3C_NORMALIZED_RISK value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_risk(const s_tlv_data *data, s_tx_simu_ctx *context) { + CHECK_FIELD_LENGTH("W3C_NORMALIZED_RISK", data->length, sizeof(context->simu->risk)); + if (data->value[0] >= RISK_MALICIOUS) { + PRINTF("W3C_NORMALIZED_RISK out of range: %d\n", data->value[0]); + return APDU_RESPONSE_INVALID_DATA; + } + context->simu->risk = data->value[0] + 1; // Because 0 is "unknown" + context->rcv_flags |= SET_BIT(BIT_W3C_NORMALIZED_RISK); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the W3C_NORMALIZED_CATEGORY value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_category(const s_tlv_data *data, s_tx_simu_ctx *context) { + CHECK_FIELD_LENGTH("W3C_NNORMALIZED_CATEGORY", data->length, sizeof(context->simu->category)); + context->simu->category = data->value[0]; + context->rcv_flags |= SET_BIT(BIT_W3C_NORMALIZED_CATEGORY); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the W3C_SIMU_TYPE value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_type(const s_tlv_data *data, s_tx_simu_ctx *context) { + CHECK_FIELD_LENGTH("W3C_SIMU_TYPE", data->length, sizeof(context->simu->type)); + if (data->value[0] >= SIMU_TYPE_PERSONAL_MESSAGE) { + PRINTF("W3C_SIMU_TYPE out of range: %d\n", data->value[0]); + return APDU_RESPONSE_INVALID_DATA; + } + context->simu->type = data->value[0] + 1; // Because 0 is "unknown" + context->rcv_flags |= SET_BIT(BIT_W3C_SIMU_TYPE); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the W3C_PROVIDER_MSG value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_provider_msg(const s_tlv_data *data, s_tx_simu_ctx *context) { + CHECK_FIELD_OVERFLOW("W3C_PROVIDER_MSG", context->simu->provider_msg, data->length); + // Check if the name is printable + if (!check_name(data->value, data->length)) { + PRINTF("W3C_PROVIDER_MSG is not printable!\n"); + return APDU_RESPONSE_INVALID_DATA; + } + COPY_FIELD(context->simu->provider_msg, data); + context->rcv_flags |= SET_BIT(BIT_W3C_PROVIDER_MSG); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the W3C_TINY_URL value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_tiny_url(const s_tlv_data *data, s_tx_simu_ctx *context) { + CHECK_FIELD_OVERFLOW("W3C_TINY_URL", context->simu->tiny_url, data->length); + // Check if the name is printable + if (!check_name(data->value, data->length)) { + PRINTF("W3C_TINY_URL is not printable!\n"); + return APDU_RESPONSE_INVALID_DATA; + } + COPY_FIELD(context->simu->tiny_url, data); + context->rcv_flags |= SET_BIT(BIT_W3C_TINY_URL); + return APDU_RESPONSE_OK; +} + +/** + * @brief Parse the SIGNATURE value. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static uint16_t parse_signature(const s_tlv_data *data, s_tx_simu_ctx *context) { + context->sig_size = data->length; + context->sig = (uint8_t *) data->value; + context->rcv_flags |= SET_BIT(BIT_DER_SIGNATURE); + return APDU_RESPONSE_OK; +} + +/** + * @brief Verify the payload signature + * + * Verify the SHA-256 hash of the payload against the public key + * + * @param[in] context TX Simu context + * @return whether it was successful + */ +static bool verify_signature(s_tx_simu_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("Tx Simulation", + hash, + sizeof(hash), + NULL, + 0, +#ifdef HAVE_LEDGER_PKI + CERTIFICATE_PUBLIC_KEY_USAGE_TX_SIMU_SIGNER, +#endif + (uint8_t *) (context->sig), + context->sig_size)); + + // Partner name is retrieved from the certificate + uint8_t key_usage = 0; + size_t trusted_name_len = 0; + uint8_t trusted_name[CERTIFICATE_TRUSTED_NAME_MAXLEN] = {0}; + cx_ecfp_384_public_key_t public_key = {0}; + if (os_pki_get_info(&key_usage, trusted_name, &trusted_name_len, &public_key) != 0) { + PRINTF("Failed to get the certificate info\n"); + goto end; + } + explicit_bzero((void *) context->simu->partner, PARTNER_SIZE); + // Last byte is the NULL terminator + memmove((void *) context->simu->partner, trusted_name, PARTNER_SIZE - 1); + ret_code = true; +end: + return ret_code; +} + +/** + * @brief Verify the received fields + * + * Check the mandatory fields are present + * + * @param[in] context TX Simu context + * @return whether it was successful + */ +static bool verify_fields(s_tx_simu_ctx *context) { + uint32_t expected_fields; + + expected_fields = (1 << BIT_STRUCTURE_TYPE) | (1 << BIT_STRUCTURE_VERSION) | + (1 << BIT_TX_HASH) | (1 << BIT_ADDRESS) | (1 << BIT_W3C_NORMALIZED_RISK) | + (1 << BIT_W3C_NORMALIZED_CATEGORY) | (1 << BIT_W3C_TINY_URL) | + (1 << BIT_W3C_SIMU_TYPE) | (1 << BIT_DER_SIGNATURE); + + if (context->simu->type == SIMU_TYPE_TRANSACTION) { + expected_fields |= (1 << BIT_CHAIN_ID); + } + if (context->simu->type == SIMU_TYPE_TYPED_DATA) { + expected_fields |= (1 << BIT_DOMAIN_HASH); + } + + return ((context->rcv_flags & expected_fields) == expected_fields); +} + +/** + * @brief Print the simulation parameters. + * + * @param[in] context TX Simu context + * Only for debug purpose. + */ +static void print_simulation_info(s_tx_simu_ctx *context) { + char chain_str[sizeof(uint64_t) * 2 + 1] = {0}; + + PRINTF("****************************************************************************\n"); + PRINTF("[TX SIMU] - Retrieved TX simulation:\n"); + PRINTF("[TX SIMU] - Partner: %s\n", context->simu->partner); + PRINTF("[TX SIMU] - Hash: %.*h\n", HASH_SIZE, context->simu->tx_hash); + PRINTF("[TX SIMU] - Address: %.*h\n", ADDRESS_LENGTH, context->simu->addr); + if (context->simu->chain_id != 0) { + u64_to_string(context->simu->chain_id, chain_str, sizeof(chain_str)); + PRINTF("[TX SIMU] - ChainID: %s\n", chain_str); + } + PRINTF("[TX SIMU] - Risk: %d -> %s\n", context->simu->risk, get_tx_simulation_risk_str()); + PRINTF("[TX SIMU] - Category: %d -> %s\n", + context->simu->category, + get_tx_simulation_category_str()); + PRINTF("[TX SIMU] - Provider Msg: %s\n", context->simu->provider_msg); + PRINTF("[TX SIMU] - Tiny URL: %s\n", context->simu->tiny_url); +} + +/** + * @brief Parse the received TLV. + * + * @param[in] data the tlv data + * @param[in] context TX Simu context + * @return APDU Response code + */ +static bool handle_tx_simu_tlv(const s_tlv_data *data, s_tx_simu_ctx *context) { + uint16_t sw = APDU_RESPONSE_INTERNAL_ERROR; + + switch (data->tag) { + case TAG_STRUCTURE_TYPE: + sw = parse_struct_type(data, context); + break; + case TAG_STRUCTURE_VERSION: + sw = parse_struct_version(data, context); + break; + case TAG_CHAIN_ID: + sw = parse_chain_id(data, context); + break; + case TAG_ADDRESS: + sw = parse_address(data, context); + break; + case TAG_TX_HASH: + sw = parse_tx_hash(data, context); + break; + case TAG_DOMAIN_HASH: + sw = parse_domain_hash(data, context); + break; + case TAG_W3C_NORMALIZED_RISK: + sw = parse_risk(data, context); + break; + case TAG_W3C_NORMALIZED_CATEGORY: + sw = parse_category(data, context); + break; + case TAG_W3C_PROVIDER_MSG: + sw = parse_provider_msg(data, context); + break; + case TAG_W3C_TINY_URL: + sw = parse_tiny_url(data, context); + break; + case TAG_W3C_SIMU_TYPE: + sw = parse_type(data, context); + break; + case TAG_DER_SIGNATURE: + sw = parse_signature(data, context); + break; + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + sw = APDU_RESPONSE_OK; + break; + } + if ((sw == APDU_RESPONSE_OK) && (data->tag != TAG_DER_SIGNATURE)) { + hash_nbytes(data->raw, data->raw_size, (cx_hash_t *) &context->hash_ctx); + } + return (sw == APDU_RESPONSE_OK); +} + +/** + * @brief Parse the TLV payload containing the TX Simulation parameters. + * + * @param[in] payload buffer received + * @param[in] size of the buffer + * @param[in] to_free if the payload needs to be freed + * @return whether the TLV payload was handled successfully or not + */ +static bool handle_tlv_payload(const uint8_t *payload, uint16_t size, bool to_free) { + bool parsing_ret; + s_tx_simu_ctx ctx = {0}; + + ctx.simu = &TX_SIMULATION; + // Reset the structures + explicit_bzero(&TX_SIMULATION, sizeof(TX_SIMULATION)); + // Initialize the hash context + cx_sha256_init(&ctx.hash_ctx); + + parsing_ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_tx_simu_tlv, &ctx); + if (to_free) mem_dealloc(size); + if (!parsing_ret || !verify_fields(&ctx) || !verify_signature(&ctx)) { + explicit_bzero(&TX_SIMULATION, sizeof(TX_SIMULATION)); + explicit_bzero(&ctx, sizeof(s_tx_simu_ctx)); + return false; + } + if (strlen(ctx.simu->partner) == 0) { + // Set a default value for partner + snprintf((char *) ctx.simu->partner, sizeof(ctx.simu->partner), "Transaction Checks"); + } + print_simulation_info(&ctx); + return true; +} + +/** + * @brief Handle Tx Simulation Opt-In. + * + * @param[in] response_expected indicates if a response is expected + */ +void handle_tx_simulation_opt_in(bool response_expected) { + if (N_storage.w3c_opt_in) { + // Web3 Checks already Opt-In + PRINTF("Web3 Checks already Opt-in!\n"); + if (response_expected) { + // just respond the current state and return to idle screen + G_io_apdu_buffer[0] = N_storage.w3c_enable; + io_seproxyhal_send_status(APDU_RESPONSE_OK, 1, false, true); + } + return; + } + ui_tx_simulation_opt_in(response_expected); +} + +/** + * @brief Handle Tx Simulation APDU. + * + * @param[in] p1 APDU parameter 1 (indicates Data payload or Opt-In request) + * @param[in] p2 APDU parameter 2 (indicates if the payload is the first chunk) + * @param[in] data buffer received + * @param[in] length of the buffer + * @return APDU Response code + */ +uint16_t handle_tx_simulation(uint8_t p1, + uint8_t p2, + const uint8_t *data, + uint8_t length, + unsigned int *flags) { + uint16_t sw = APDU_RESPONSE_INTERNAL_ERROR; + + switch (p1) { + case 0x00: + // TX Simulation data + if (!N_storage.w3c_enable) { + PRINTF("Error: Web3 check is disabled!\n"); + sw = APDU_RESPONSE_CMD_CODE_NOT_SUPPORTED; + break; + } + if (!tlv_from_apdu(p2 == P1_FIRST_CHUNK, length, data, &handle_tlv_payload)) { + sw = APDU_RESPONSE_INVALID_DATA; + } else { + sw = APDU_RESPONSE_OK; + } + break; + case 0x01: + // TX Simulation Opt-In + handle_tx_simulation_opt_in(true); + *flags |= IO_ASYNCH_REPLY; + sw = APDU_NO_RESPONSE; + break; + default: + PRINTF("Error: Unexpected P1 (%u)!\n", p1); + sw = APDU_RESPONSE_INVALID_P1_P2; + break; + } + return sw; +} + +/** + * @brief Clear the TX Simulation parameters. + * + */ +void clear_tx_simulation(void) { + explicit_bzero(&TX_SIMULATION, sizeof(TX_SIMULATION)); +} + +/** + * @brief Check the TX HASH vs Simulation payload. + * + * @return whether it was successful + */ +bool check_tx_simulation_hash(void) { + uint8_t *hash = NULL; + uint8_t *hash2 = NULL; + + if (!N_storage.w3c_enable) { + // W3Checks disabled + return true; + } + switch (appState) { + case APP_STATE_SIGNING_TX: + hash = tmpCtx.transactionContext.hash; + break; + case APP_STATE_SIGNING_MESSAGE: + hash = tmpCtx.messageSigningContext.hash; + break; + case APP_STATE_SIGNING_EIP712: + hash = tmpCtx.messageSigningContext712.messageHash; + hash2 = tmpCtx.messageSigningContext712.domainHash; + break; + default: + PRINTF("[TX SIMU] Invalid app State %d!\n", appState); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + if (memcmp(TX_SIMULATION.tx_hash, hash, HASH_SIZE) != 0) { + PRINTF("[TX SIMU] TX_HASH mismatch: %.*h != %.*h\n", + HASH_SIZE, + TX_SIMULATION.tx_hash, + HASH_SIZE, + hash); + PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + if ((hash2 != NULL) && (memcmp(TX_SIMULATION.domain_hash, hash2, HASH_SIZE)) != 0) { + PRINTF("[TX SIMU] DOMAIN_HASH mismatch: %.*h != %.*h\n", + HASH_SIZE, + TX_SIMULATION.domain_hash, + HASH_SIZE, + hash); + PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + return true; +} + +/** + * @brief Check the FROM_ADDRESS vs Simulation payload. + * + * @return whether it was successful + */ +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"); + PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + if (memcmp(TX_SIMULATION.addr, msg_sender, ADDRESS_LENGTH) != 0) { + PRINTF("[TX SIMU] FROM addr mismatch: %.*h != %.*h\n", + ADDRESS_LENGTH, + TX_SIMULATION.addr, + ADDRESS_LENGTH, + msg_sender); + PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + return true; +} + +/** + * @brief Check the TX vs Simulation parameters (CHAIN_ID, TX_HASH). + * + * @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) { + uint64_t chain_id = get_tx_chain_id(); + + if (!N_storage.w3c_enable) { + // W3Checks disabled + return true; + } + switch (TX_SIMULATION.type) { + case SIMU_TYPE_TRANSACTION: + if (appState != APP_STATE_SIGNING_TX) { + PRINTF("[TX SIMU] Simulation type inconsistent!\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + break; + case SIMU_TYPE_PERSONAL_MESSAGE: + if (appState != APP_STATE_SIGNING_MESSAGE) { + PRINTF("[TX SIMU] Simulation type inconsistent!\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + break; + case SIMU_TYPE_TYPED_DATA: + if (appState != APP_STATE_SIGNING_EIP712) { + PRINTF("[TX SIMU] Simulation type inconsistent!\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + break; + default: + // No simulation data + PRINTF("[TX SIMU] Simulation type is not set\n"); + PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; + } + if (TX_SIMULATION.risk == RISK_UNKNOWN) { + // No simulation data + PRINTF("[TX SIMU] Simulation risk is not set\n"); + 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 false; + } + if (checkFromAddr) { + if (check_tx_simulation_from_address() == false) { + return false; + } + } + if (checkTxHash) { + if (check_tx_simulation_hash() == false) { + return false; + } + } + return true; +} + +/** + * @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) { + if (!N_storage.w3c_enable) { + // W3Checks disabled + return; + } + // W3Checks enabled => Verify parameters of the Transaction + check_tx_simulation_params(checkTxHash, checkFromAddr); + switch (TX_SIMULATION.risk) { + case RISK_UNKNOWN: + p_warning->predefinedSet |= SET_BIT(W3C_ISSUE_WARN); + break; + case RISK_BENIGN: + p_warning->predefinedSet |= SET_BIT(W3C_NO_THREAT_WARN); + break; + case RISK_WARNING: + p_warning->predefinedSet |= SET_BIT(W3C_RISK_DETECTED_WARN); + break; + case RISK_MALICIOUS: + p_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); +} + +/** + * @brief Retrieve the TX Simulation risk string. + * + * @return risk as a string + */ +const char *get_tx_simulation_risk_str(void) { + switch (TX_SIMULATION.risk) { + case RISK_UNKNOWN: + return "UNKNOWN (W3C Issue)"; + case RISK_BENIGN: + return "BENIGN"; + case RISK_WARNING: + return "RISK (WARNING)"; + case RISK_MALICIOUS: + return "THREAT (MALICIOUS)"; + default: + break; + } + return "INVALID"; +} + +/** + * @brief Retrieve the TX Simulation category string. + * + * @return category string + */ +const char *get_tx_simulation_category_str(void) { + // Unknown category string + switch (TX_SIMULATION.risk) { + case RISK_UNKNOWN: + case RISK_BENIGN: + break; + case RISK_WARNING: + switch (TX_SIMULATION.category) { + case CATEGORY_ADDRESS: + return "This transaction involves a suspicious address. " + "It might not be safe to continue."; + case CATEGORY_DAPP: + return "This transaction involves a suspicious dApp. " + "It might not be safe to continue."; + case CATEGORY_LOSING_OPERATION: + return "This transaction could end in a loss. " + "Check transaction details carefully before signing."; + default: + return "This transaction might be malicious. It might not be safe to continue. " + "Tap the QR code icon for more details."; + break; + } + break; + case RISK_MALICIOUS: + switch (TX_SIMULATION.category) { + case CATEGORY_ADDRESS: + return "This transaction involves a malicious address. " + "Your assets will most likely be stolen."; + case CATEGORY_DAPP: + return "This dApp is linked to a scammer. " + "Your assets will most likely be stolen."; + default: + return "This request is malicious. Your assets will most likely be stolen. " + "View full report for details."; + } + break; + } + return "Unknown"; +} + +#endif // HAVE_WEB3_CHECKS diff --git a/src_features/provide_tx_simulation/cmd_get_tx_simulation.h b/src_features/provide_tx_simulation/cmd_get_tx_simulation.h new file mode 100644 index 0000000000..2148df97fb --- /dev/null +++ b/src_features/provide_tx_simulation/cmd_get_tx_simulation.h @@ -0,0 +1,72 @@ +#pragma once + +#ifdef HAVE_WEB3_CHECKS + +#include +#include +#include "common_utils.h" +#include "nbgl_use_case.h" +#ifdef HAVE_LEDGER_PKI +#include "os_pki.h" +#endif + +#define HASH_SIZE 32 +#define MSG_SIZE 25 +#define URL_SIZE 30 +#define PARTNER_SIZE 20 + +// clang-format off +typedef enum { + RISK_UNKNOWN, + RISK_BENIGN, + RISK_WARNING, + RISK_MALICIOUS +} tx_simulation_score_t; +// clang-format on + +typedef enum { + SIMU_TYPE_UNKNOWN, + SIMU_TYPE_TRANSACTION, + SIMU_TYPE_TYPED_DATA, + SIMU_TYPE_PERSONAL_MESSAGE +} tx_simulation_type_t; + +typedef struct tx_simu_s { + uint64_t chain_id; + const char tx_hash[HASH_SIZE]; + const char domain_hash[HASH_SIZE]; + const char provider_msg[MSG_SIZE + 1]; // +1 for the null terminator + const char tiny_url[URL_SIZE + 1]; // +1 for the null terminator + const char addr[ADDRESS_LENGTH]; + const char partner[PARTNER_SIZE]; + tx_simulation_score_t risk; + tx_simulation_type_t type; + uint8_t category; +} tx_simulation_t; + +_Static_assert(CERTIFICATE_TRUSTED_NAME_MAXLEN > PARTNER_SIZE - 1, + "Partner size is too big to get the trusted name"); + +// Global structure to store the tx simultion parameters +extern tx_simulation_t TX_SIMULATION; + +uint16_t handle_tx_simulation(uint8_t p1, + uint8_t p2, + const uint8_t *data, + 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); + +const char *get_tx_simulation_risk_str(void); +const char *get_tx_simulation_category_str(void); + +#endif // HAVE_WEB3_CHECKS + +const char *ui_tx_simulation_finish_str(void); diff --git a/src_features/setExternalPlugin/cmd_setExternalPlugin.c b/src_features/setExternalPlugin/cmd_setExternalPlugin.c index 6ab3b3915d..073b3ae265 100644 --- a/src_features/setExternalPlugin/cmd_setExternalPlugin.c +++ b/src_features/setExternalPlugin/cmd_setExternalPlugin.c @@ -1,11 +1,8 @@ -#include "shared_context.h" #include "apdu_constants.h" #include "public_keys.h" #include "eth_plugin_interface.h" #include "eth_plugin_internal.h" #include "plugin_utils.h" -#include "common_ui.h" -#include "os_io_seproxyhal.h" #ifdef HAVE_LEDGER_PKI #include "os_pki.h" #endif @@ -68,6 +65,7 @@ uint16_t handleSetExternalPlugin(const uint8_t *workBuffer, uint8_t dataLength) os_lib_call(params); } CATCH_OTHER(e) { + (void) e; PRINTF("%s external plugin is not present\n", dataContext.tokenContext.pluginName); memset(dataContext.tokenContext.pluginName, 0, diff --git a/src_features/setPlugin/cmd_setPlugin.c b/src_features/setPlugin/cmd_setPlugin.c index 91455b4ce0..2933c7955b 100644 --- a/src_features/setPlugin/cmd_setPlugin.c +++ b/src_features/setPlugin/cmd_setPlugin.c @@ -1,12 +1,7 @@ -#include "shared_context.h" #include "apdu_constants.h" -#include "asset_info.h" #include "eth_plugin_interface.h" #include "eth_plugin_internal.h" #include "plugin_utils.h" -#include "common_utils.h" -#include "common_ui.h" -#include "os_io_seproxyhal.h" #include "network.h" #include "public_keys.h" #ifdef HAVE_LEDGER_PKI @@ -239,6 +234,7 @@ uint16_t handleSetPlugin(const uint8_t *workBuffer, uint8_t dataLength) { os_lib_call(params); } CATCH_OTHER(e) { + (void) e; PRINTF("%s external plugin is not present\n", tokenContext->pluginName); memset(tokenContext->pluginName, 0, sizeof(tokenContext->pluginName)); CLOSE_TRY; diff --git a/src_features/signMessage/cmd_signMessage.c b/src_features/signMessage/cmd_signMessage.c index e9549c4f94..f502872701 100644 --- a/src_features/signMessage/cmd_signMessage.c +++ b/src_features/signMessage/cmd_signMessage.c @@ -1,9 +1,8 @@ -#include #include -#include #include "apdu_constants.h" #include "sign_message.h" #include "common_ui.h" +#include "ui_callbacks.h" static uint8_t processed_size; static struct { diff --git a/src_features/signMessage/ui_common_signMessage.c b/src_features/signMessage/ui_common_signMessage.c index 047b21a37d..feb6c606c0 100644 --- a/src_features/signMessage/ui_common_signMessage.c +++ b/src_features/signMessage/ui_common_signMessage.c @@ -1,7 +1,7 @@ #include "os_io_seproxyhal.h" #include "apdu_constants.h" #include "crypto_helpers.h" -#include "common_ui.h" +#include "ui_callbacks.h" unsigned int io_seproxyhal_touch_signMessage_ok(void) { unsigned int info = 0; diff --git a/src_features/signMessageEIP712/commands_712.c b/src_features/signMessageEIP712/commands_712.c index dd3485a7e5..c8f44ba187 100644 --- a/src_features/signMessageEIP712/commands_712.c +++ b/src_features/signMessageEIP712/commands_712.c @@ -1,9 +1,5 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include -#include -#include -#include "commands_712.h" #include "apdu_constants.h" // APDU response codes #include "context_712.h" #include "field_hash.h" @@ -12,9 +8,9 @@ #include "typed_data.h" #include "schema_hash.h" #include "filtering.h" -#include "common_712.h" #include "common_ui.h" // ui_idle #include "manage_asset_info.h" +#include "ui_callbacks.h" // APDUs P1 #define P1_COMPLETE 0x00 diff --git a/src_features/signMessageEIP712/context_712.c b/src_features/signMessageEIP712/context_712.c index 89a2a98b04..79d3bed647 100644 --- a/src_features/signMessageEIP712/context_712.c +++ b/src_features/signMessageEIP712/context_712.c @@ -1,7 +1,5 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include -#include #include "context_712.h" #include "mem.h" #include "mem_utils.h" diff --git a/src_features/signMessageEIP712/encode_field.c b/src_features/signMessageEIP712/encode_field.c index 2c3339d4b4..bffade56d3 100644 --- a/src_features/signMessageEIP712/encode_field.c +++ b/src_features/signMessageEIP712/encode_field.c @@ -1,10 +1,7 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include -#include #include "encode_field.h" #include "mem.h" -#include "shared_context.h" #include "apdu_constants.h" // APDU response codes typedef enum { MSB, LSB } e_padding_type; diff --git a/src_features/signMessageEIP712/field_hash.c b/src_features/signMessageEIP712/field_hash.c index 0818be8562..73d9e06a4a 100644 --- a/src_features/signMessageEIP712/field_hash.c +++ b/src_features/signMessageEIP712/field_hash.c @@ -6,7 +6,6 @@ #include "path.h" #include "mem.h" #include "mem_utils.h" -#include "shared_context.h" #include "ui_logic.h" #include "context_712.h" // contract_addr #include "common_utils.h" // u64_from_BE diff --git a/src_features/signMessageEIP712/filtering.c b/src_features/signMessageEIP712/filtering.c index 232043679c..dfd4a651bc 100644 --- a/src_features/signMessageEIP712/filtering.c +++ b/src_features/signMessageEIP712/filtering.c @@ -15,6 +15,7 @@ #include "os_pki.h" #endif #include "trusted_name.h" +#include "proxy_info.h" #define FILT_MAGIC_MESSAGE_INFO 183 #define FILT_MAGIC_AMOUNT_JOIN_TOKEN 11 @@ -80,6 +81,7 @@ static void hash_filtering_path(cx_hash_t *hash_ctx, bool discarded, uint32_t *p */ static bool sig_verif_start(cx_sha256_t *hash_ctx, uint8_t magic) { uint64_t chain_id; + const uint8_t *addr; cx_sha256_init(hash_ctx); @@ -91,9 +93,14 @@ static bool sig_verif_start(cx_sha256_t *hash_ctx, uint8_t magic) { hash_nbytes((uint8_t *) &chain_id, sizeof(chain_id), (cx_hash_t *) hash_ctx); // Contract address - hash_nbytes(eip712_context->contract_addr, - sizeof(eip712_context->contract_addr), - (cx_hash_t *) hash_ctx); + // we can't compare the returned address with anything since filtering payloads are signed on an + // address which is not provided + if ((addr = + get_proxy_contract(&eip712_context->chain_id, eip712_context->contract_addr, NULL)) == + NULL) { + addr = eip712_context->contract_addr; + } + hash_nbytes(addr, ADDRESS_LENGTH, (cx_hash_t *) hash_ctx); // Schema hash hash_nbytes(eip712_context->schema_hash, diff --git a/src_features/signMessageEIP712/path.c b/src_features/signMessageEIP712/path.c index c163a4bb41..e186279e55 100644 --- a/src_features/signMessageEIP712/path.c +++ b/src_features/signMessageEIP712/path.c @@ -1,13 +1,11 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include #include #include "path.h" #include "mem.h" #include "context_712.h" #include "commands_712.h" #include "type_hash.h" -#include "shared_context.h" #include "mem_utils.h" #include "apdu_constants.h" // APDU response codes #include "typed_data.h" diff --git a/src_features/signMessageEIP712/sol_typenames.c b/src_features/signMessageEIP712/sol_typenames.c index 6163e7fa94..0d09e56bd1 100644 --- a/src_features/signMessageEIP712/sol_typenames.c +++ b/src_features/signMessageEIP712/sol_typenames.c @@ -1,7 +1,5 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include -#include #include "sol_typenames.h" #include "mem.h" #include "os_pic.h" diff --git a/src_features/signMessageEIP712/type_hash.c b/src_features/signMessageEIP712/type_hash.c index 8318abcfd9..a005718d7d 100644 --- a/src_features/signMessageEIP712/type_hash.c +++ b/src_features/signMessageEIP712/type_hash.c @@ -1,12 +1,8 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include -#include -#include #include "mem.h" #include "mem_utils.h" #include "type_hash.h" -#include "shared_context.h" #include "format_hash_field_type.h" #include "hash_bytes.h" #include "apdu_constants.h" // APDU response codes diff --git a/src_features/signMessageEIP712/typed_data.c b/src_features/signMessageEIP712/typed_data.c index e5f75b7000..703223758f 100644 --- a/src_features/signMessageEIP712/typed_data.c +++ b/src_features/signMessageEIP712/typed_data.c @@ -1,7 +1,5 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include -#include #include "typed_data.h" #include "sol_typenames.h" #include "apdu_constants.h" // APDU response codes diff --git a/src_features/signMessageEIP712/ui_logic.c b/src_features/signMessageEIP712/ui_logic.c index d022fcb13c..309a02321e 100644 --- a/src_features/signMessageEIP712/ui_logic.c +++ b/src_features/signMessageEIP712/ui_logic.c @@ -1,25 +1,18 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include -#include -#include #include "ui_logic.h" #include "mem.h" #include "mem_utils.h" #include "os_io.h" -#include "shared_context.h" #include "common_utils.h" // uint256_to_decimal #include "common_712.h" #include "context_712.h" // eip712_context_deinit -#include "uint256.h" // tostring256 && tostring256_signed #include "path.h" // path_get_root_type #include "apdu_constants.h" // APDU response codes #include "typed_data.h" #include "commands_712.h" #include "common_ui.h" -#include "uint_common.h" #include "filtering.h" -#include "trusted_name.h" #include "network.h" #include "time_format.h" diff --git a/src_features/signMessageEIP712_common/common_712.c b/src_features/signMessageEIP712_common/common_712.c index bdf64cbd1a..50daac84f2 100644 --- a/src_features/signMessageEIP712_common/common_712.c +++ b/src_features/signMessageEIP712_common/common_712.c @@ -1,11 +1,8 @@ -#include "shared_context.h" #include "apdu_constants.h" #include "os_io_seproxyhal.h" #include "crypto_helpers.h" #include "ui_callbacks.h" #include "common_712.h" -#include "ui_callbacks.h" -#include "common_ui.h" static const uint8_t EIP_712_MAGIC[] = {0x19, 0x01}; diff --git a/src_features/signMessageEIP712_v0/cmd_signMessage712.c b/src_features/signMessageEIP712_v0/cmd_signMessage712.c index 844a3c8fc8..e829f47e3f 100644 --- a/src_features/signMessageEIP712_v0/cmd_signMessage712.c +++ b/src_features/signMessageEIP712_v0/cmd_signMessage712.c @@ -1,4 +1,3 @@ -#include "shared_context.h" #include "apdu_constants.h" #include "common_utils.h" #include "common_ui.h" diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index 0bece7eb7d..cea6cc4a61 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -3,10 +3,12 @@ #include "feature_signTx.h" #include "eth_plugin_interface.h" #include "apdu_constants.h" +#include "swap_error_code_helpers.h" #ifdef HAVE_GENERIC_TX_PARSER #include "gtp_tx_info.h" #endif #include "common_ui.h" +#include "ui_callbacks.h" typedef enum { SIGN_MODE_BASIC = 0, @@ -84,7 +86,9 @@ uint16_t handle_parsing_status(parserStatus_e status) { // We have encountered an error while trying to sign a SWAP type transaction // Return dedicated error code and flag an early exit back to Exchange G_swap_response_ready = true; - send_swap_error(ERROR_GENERIC, APP_CODE_CALLDATA_ISSUE, NULL, NULL); + send_swap_error_simple(APDU_RESPONSE_MODE_CHECK_FAILED, + SWAP_EC_ERROR_GENERIC, + APP_CODE_CALLDATA_ISSUE); // unreachable os_sched_exit(0); } diff --git a/src_features/signTx/feature_signTx.h b/src_features/signTx/feature_signTx.h index 9f0af6371e..6a23e6d9b4 100644 --- a/src_features/signTx/feature_signTx.h +++ b/src_features/signTx/feature_signTx.h @@ -5,15 +5,6 @@ #include #include "ethUstream.h" -// Error codes for swap, to be moved in SDK? -#define ERROR_WRONG_AMOUNT 0x01 -#define ERROR_WRONG_DESTINATION 0x02 -#define ERROR_WRONG_FEES 0x03 -#define ERROR_WRONG_METHOD 0x04 -#define ERROR_CROSSCHAIN_WRONG_MODE 0x05 -#define ERROR_CROSSCHAIN_WRONG_METHOD 0x06 -#define ERROR_GENERIC 0xFF - // App codes for detail. typedef enum { APP_CODE_DEFAULT = 0x00, @@ -33,8 +24,6 @@ uint16_t finalize_parsing(const txContext_t *context); void ux_approve_tx(bool fromPlugin); void start_signature_flow(void); -void send_swap_error(uint8_t error_code, app_code_t app_code, const char *str1, const char *str2); - uint16_t handle_parsing_status(parserStatus_e status); uint16_t get_public_key(uint8_t *out, uint8_t outLength); diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 6d3c304ca7..ffc6294400 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -14,6 +14,7 @@ #include "handle_swap_sign_transaction.h" #include "os_math.h" #include "calldata.h" +#include "swap_error_code_helpers.h" static bool g_use_standard_ui; @@ -338,56 +339,6 @@ static int strcasecmp_workaround(const char *str1, const char *str2) { return 0; } -__attribute__((noreturn)) void send_swap_error(uint8_t error_code, - app_code_t app_code, - const char *str1, - const char *str2) { - uint32_t tx = 0; - size_t len = 0; - PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED: 0x%x\n", error_code); - // Set RAPDU error codes - G_io_apdu_buffer[tx++] = error_code; - G_io_apdu_buffer[tx++] = app_code; - // Set RAPDU error message - if (str1 != NULL) { - PRINTF("Expected %s\n", str1); - // If the string is too long, truncate it - len = MIN(strlen((const char *) str1), sizeof(G_io_apdu_buffer) - tx - 2); - memmove(G_io_apdu_buffer + tx, str1, len); - tx += len; - if (len < strlen((const char *) str1)) { - PRINTF("Truncated %s to %d bytes\n", str1, len); - G_io_apdu_buffer[tx - 1] = '*'; - } - } - if (str2 != NULL) { - PRINTF("Received %s\n", str2); - // Do we have enough space to add a separator? - if ((tx + 1 + 2) < sizeof(G_io_apdu_buffer)) { - G_io_apdu_buffer[tx++] = '#'; - } - // Do we have enough space to add at least one character? - if ((tx + 1 + 2) < sizeof(G_io_apdu_buffer)) { - // If the string is too long, truncate it - len = MIN(strlen((const char *) str2), sizeof(G_io_apdu_buffer) - tx - 2); - memmove(G_io_apdu_buffer + tx, str2, len); - tx += len; - if (len < strlen((const char *) str2)) { - PRINTF("Truncated %s to %d bytes\n", str2, len); - G_io_apdu_buffer[tx - 1] = '*'; - } - } - } - // Set RAPDU status word, with previous check we are sure there is at least 2 bytes left - U2BE_ENCODE(G_io_apdu_buffer, tx, APDU_RESPONSE_MODE_CHECK_FAILED); - tx += 2; - // Send RAPDU - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx); - // In case of success, the apdu is sent immediately and eth exits - // Reaching this code means we encountered an error - finalize_exchange_sign_transaction(false); -} - __attribute__((noinline)) static uint16_t finalize_parsing_helper(const txContext_t *context) { char displayBuffer[50]; uint8_t decimals = WEI_TO_ETHER; @@ -435,7 +386,8 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(const txContex pluginFinalize.address = msg_sender; - if (!eth_plugin_call(ETH_PLUGIN_FINALIZE, (void *) &pluginFinalize)) { + if (eth_plugin_call(ETH_PLUGIN_FINALIZE, (void *) &pluginFinalize) < + ETH_PLUGIN_RESULT_SUCCESSFUL) { PRINTF("Plugin finalize call failed\n"); report_finalize_error(); return APDU_NO_RESPONSE; @@ -522,14 +474,18 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(const txContex // User has just validated a swap but ETH received apdus about a non standard plugin / // contract if (!g_use_standard_ui) { - send_swap_error(ERROR_WRONG_METHOD, APP_CODE_NO_STANDARD_UI, NULL, NULL); + send_swap_error_simple(APDU_RESPONSE_MODE_CHECK_FAILED, + SWAP_EC_ERROR_WRONG_METHOD, + APP_CODE_NO_STANDARD_UI); // unreachable os_sched_exit(0); } // Two success cases: we are in standard mode and no calldata was received // We are in crosschain mode and the correct calldata has been received if (G_swap_mode != SWAP_MODE_STANDARD && G_swap_mode != SWAP_MODE_CROSSCHAIN_SUCCESS) { - send_swap_error(ERROR_CROSSCHAIN_WRONG_MODE, APP_CODE_DEFAULT, NULL, NULL); + send_swap_error_simple(APDU_RESPONSE_MODE_CHECK_FAILED, + SWAP_EC_ERROR_CROSSCHAIN_WRONG_MODE, + APP_CODE_DEFAULT); // unreachable os_sched_exit(0); } @@ -564,10 +520,13 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(const txContex if (G_called_from_swap) { // Ensure the values are the same that the ones that have been previously validated if (strcasecmp_workaround(strings.common.toAddress, displayBuffer) != 0) { - send_swap_error(ERROR_WRONG_DESTINATION, - APP_CODE_DEFAULT, - strings.common.toAddress, - displayBuffer); + PRINTF("Error comparing destination addresses\n"); + send_swap_error_with_string(APDU_RESPONSE_MODE_CHECK_FAILED, + SWAP_EC_ERROR_WRONG_DESTINATION, + APP_CODE_DEFAULT, + "%s != %s", + strings.common.toAddress, + displayBuffer); // unreachable os_sched_exit(0); } @@ -591,10 +550,13 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(const txContex if (G_called_from_swap) { // Ensure the values are the same that the ones that have been previously validated if (strcmp(strings.common.fullAmount, displayBuffer) != 0) { - send_swap_error(ERROR_WRONG_AMOUNT, - APP_CODE_DEFAULT, - strings.common.fullAmount, - displayBuffer); + PRINTF("Error comparing amounts\n"); + send_swap_error_with_string(APDU_RESPONSE_MODE_CHECK_FAILED, + SWAP_EC_ERROR_WRONG_AMOUNT, + APP_CODE_DEFAULT, + "%s != %s", + strings.common.fullAmount, + displayBuffer); // unreachable os_sched_exit(0); } @@ -615,10 +577,13 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(const txContex if (G_called_from_swap) { // Ensure the values are the same that the ones that have been previously validated if (strcmp(strings.common.maxFee, displayBuffer) != 0) { - send_swap_error(ERROR_WRONG_FEES, - APP_CODE_DEFAULT, - strings.common.maxFee, - displayBuffer); + PRINTF("Error comparing fees\n"); + send_swap_error_with_string(APDU_RESPONSE_MODE_CHECK_FAILED, + SWAP_EC_ERROR_WRONG_FEES, + APP_CODE_DEFAULT, + "%s != %s", + strings.common.maxFee, + displayBuffer); // unreachable os_sched_exit(0); } @@ -675,7 +640,6 @@ uint16_t finalize_parsing(const txContext_t *context) { // If called from swap, the user has already validated a standard transaction // And we have already checked the fields of this transaction above if (G_called_from_swap && g_use_standard_ui) { - ui_idle(); io_seproxyhal_touch_tx_ok(); } else { #ifdef HAVE_BAGL diff --git a/src_features/signTx/ui_common_signTx.c b/src_features/signTx/ui_common_signTx.c index 6a6cf7ea2f..30a9bdd312 100644 --- a/src_features/signTx/ui_common_signTx.c +++ b/src_features/signTx/ui_common_signTx.c @@ -1,11 +1,9 @@ +#include "swap_entrypoints.h" #include "crypto_helpers.h" -#include "os_io_seproxyhal.h" -#include "shared_context.h" -#include "common_utils.h" -#include "common_ui.h" #include "handle_swap_sign_transaction.h" #include "feature_signTx.h" #include "apdu_constants.h" +#include "ui_callbacks.h" uint32_t io_seproxyhal_touch_tx_ok(void) { uint32_t info = 0; @@ -58,7 +56,7 @@ uint32_t io_seproxyhal_touch_tx_ok(void) { // If we are in swap mode and have validated a TX, we send it and immediately quit if (err == 0) { - finalize_exchange_sign_transaction(true); + swap_finalize_exchange_sign_transaction(true); } else { PRINTF("Unrecoverable\n"); app_exit(); diff --git a/src_nbgl/network_icons.c b/src_nbgl/network_icons.c index ccd1a4090b..3777a93ac6 100644 --- a/src_nbgl/network_icons.c +++ b/src_nbgl/network_icons.c @@ -1,7 +1,7 @@ #include "os_utils.h" #include "os_pic.h" #include "network.h" -#include "network_dynamic.h" +#include "network_info.h" #include "net_icons.gen.h" /** diff --git a/src_nbgl/network_icons.h b/src_nbgl/network_icons.h index 0a85afebff..7eec96ddf2 100644 --- a/src_nbgl/network_icons.h +++ b/src_nbgl/network_icons.h @@ -1,9 +1,6 @@ #ifndef NETWORK_ICONS_H_ #define NETWORK_ICONS_H_ -#include -#include "nbgl_types.h" - const nbgl_icon_details_t *get_network_icon_from_chain_id(const uint64_t *chain_id); #endif // NETWORK_ICONS_H_ diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c index 300b4fa7c2..d27e749d05 100644 --- a/src_nbgl/ui_approve_tx.c +++ b/src_nbgl/ui_approve_tx.c @@ -1,15 +1,15 @@ #include -#include "nbgl_page.h" #include "shared_context.h" #include "ui_callbacks.h" +#include "ui_message_signing.h" #include "ui_nbgl.h" -#include "ui_signing.h" #include "plugins.h" #include "trusted_name.h" #include "caller_api.h" #include "network_icons.h" #include "network.h" -#include "ledger_assert.h" +#include "cmd_get_tx_simulation.h" +#include "utils.h" // 1 more than actually displayed on screen, because of calculations in StaticReview #define MAX_PLUGIN_ITEMS 8 @@ -43,6 +43,9 @@ static void reviewChoice(bool confirm) { memset(&tx_approval_context, 0, sizeof(tx_approval_context)); nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, ui_idle); } +#ifdef HAVE_WEB3_CHECKS + clear_tx_simulation(); +#endif } const nbgl_icon_details_t *get_tx_icon(void) { @@ -185,11 +188,14 @@ static uint8_t setTagValuePairs(void) { } void ux_approve_tx(bool fromPlugin) { + uint64_t chain_id = 0; + uint16_t buf_size = SHARED_BUFFER_SIZE / 2; + explicit_bzero(&pairsList, sizeof(pairsList)); explicit_bzero(&tx_approval_context, sizeof(tx_approval_context)); tx_approval_context.fromPlugin = fromPlugin; - uint64_t chain_id = get_tx_chain_id(); + chain_id = get_tx_chain_id(); if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) { tx_approval_context.displayNetwork = true; } else { @@ -199,7 +205,14 @@ void ux_approve_tx(bool fromPlugin) { pairsList.nbPairs = setTagValuePairs(); pairsList.pairs = pairs; - uint32_t buf_size = SHARED_BUFFER_SIZE / 2; + explicit_bzero(&warning, sizeof(nbgl_warning_t)); + if (tmpContent.txContent.dataPresent) { + warning.predefinedSet |= SET_BIT(BLIND_SIGNING_WARN); + } +#ifdef HAVE_WEB3_CHECKS + set_tx_simulation_warning(&warning, true, true); +#endif + if (tx_approval_context.fromPlugin) { char op_name[sizeof(strings.common.fullAmount)]; plugin_ui_get_id(); @@ -207,35 +220,27 @@ void ux_approve_tx(bool fromPlugin) { get_lowercase_operation(op_name, sizeof(op_name)); snprintf(g_stax_shared_buffer, buf_size, - "Review transaction\nto %s\n%s%s", + "Review transaction to %s %s%s", op_name, (pluginType == EXTERNAL ? "on " : ""), strings.common.toAddress); // Finish text: replace "Review" by "Sign" and add questionmark snprintf(g_stax_shared_buffer + buf_size, buf_size, - "Sign transaction\nto %s\n%s%s", + "%s transaction to %s %s%s?", + ui_tx_simulation_finish_str(), op_name, (pluginType == EXTERNAL ? "on " : ""), strings.common.toAddress); } else { - snprintf(g_stax_shared_buffer, buf_size, REVIEW("transaction")); - snprintf( - g_stax_shared_buffer + buf_size, - buf_size, - tmpContent.txContent.dataPresent ? BLIND_SIGN("transaction") : SIGN("transaction")); + snprintf(g_stax_shared_buffer, buf_size, "Review transaction"); + snprintf(g_stax_shared_buffer + buf_size, + buf_size, + "%s transaction?", + ui_tx_simulation_finish_str()); } - if (tmpContent.txContent.dataPresent) { - nbgl_useCaseReviewBlindSigning(TYPE_TRANSACTION, - &pairsList, - get_tx_icon(), - g_stax_shared_buffer, - NULL, - g_stax_shared_buffer + buf_size, - NULL, - reviewChoice); - } else { + if (warning.predefinedSet == 0) { nbgl_useCaseReview(TYPE_TRANSACTION, &pairsList, get_tx_icon(), @@ -243,5 +248,15 @@ void ux_approve_tx(bool fromPlugin) { NULL, g_stax_shared_buffer + buf_size, reviewChoice); + } else { + nbgl_useCaseAdvancedReview(TYPE_TRANSACTION, + &pairsList, + get_tx_icon(), + g_stax_shared_buffer, + NULL, + g_stax_shared_buffer + buf_size, + NULL, + &warning, + reviewChoice); } } diff --git a/src_nbgl/ui_blind_signing.c b/src_nbgl/ui_blind_signing.c index d5ad753c80..173a12e642 100644 --- a/src_nbgl/ui_blind_signing.c +++ b/src_nbgl/ui_blind_signing.c @@ -1,9 +1,4 @@ -#include -#include "shared_context.h" -#include "ui_callbacks.h" #include "ui_nbgl.h" -#include "apdu_constants.h" -#include "context_712.h" static void ui_error_blind_signing_choice(bool confirm) { if (confirm) { @@ -14,7 +9,7 @@ static void ui_error_blind_signing_choice(bool confirm) { } void ui_error_blind_signing(void) { - nbgl_useCaseChoice(&C_Warning_64px, + nbgl_useCaseChoice(&ICON_APP_WARNING, "This transaction cannot be clear-signed", "Enable blind signing in the settings to sign this transaction.", "Go to settings", diff --git a/src_nbgl/ui_confirm_parameter_selector.c b/src_nbgl/ui_confirm_parameter_selector.c index 2292e62263..520a8daa0e 100644 --- a/src_nbgl/ui_confirm_parameter_selector.c +++ b/src_nbgl/ui_confirm_parameter_selector.c @@ -1,7 +1,5 @@ -#include "common_ui.h" -#include "ui_signing.h" #include "ui_nbgl.h" -#include "network.h" +#include "ui_callbacks.h" typedef enum { PARAMETER_CONFIRMATION, SELECTOR_CONFIRMATION } e_confirmation_type; static nbgl_contentTagValue_t pair; diff --git a/src_nbgl/ui_display_privacy.c b/src_nbgl/ui_display_privacy.c index 209e0d99b4..edcd8a304e 100644 --- a/src_nbgl/ui_display_privacy.c +++ b/src_nbgl/ui_display_privacy.c @@ -1,8 +1,5 @@ -#include "common_ui.h" -#include "ui_signing.h" #include "ui_nbgl.h" -#include "nbgl_use_case.h" -#include "nbgl_content.h" +#include "ui_callbacks.h" static void reviewChoice(bool confirm) { if (confirm) { diff --git a/src_nbgl/ui_gcs.c b/src_nbgl/ui_gcs.c index 8f842837db..4d0a38d6cb 100644 --- a/src_nbgl/ui_gcs.c +++ b/src_nbgl/ui_gcs.c @@ -10,6 +10,7 @@ #include "ui_callbacks.h" #include "feature_signTx.h" #include "apdu_constants.h" +#include "cmd_get_tx_simulation.h" static nbgl_layoutTagValueList_t g_pair_list; static size_t g_alloc_size; @@ -59,7 +60,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { return false; } if ((value = get_creator_legal_name()) != NULL) { - snprintf(tmp_buf, tmp_buf_size, "Contract owner"); + snprintf(tmp_buf, tmp_buf_size, "Smart contract owner"); if ((keys[count] = _strdup(tmp_buf)) == NULL) { return false; } @@ -75,7 +76,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { } if ((value = get_contract_name()) != NULL) { - snprintf(tmp_buf, tmp_buf_size, "Contract"); + snprintf(tmp_buf, tmp_buf_size, "Smart contract"); if ((keys[count] = _strdup(tmp_buf)) == NULL) { return false; } @@ -145,57 +146,81 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { bool ui_gcs(void) { char *tmp_buf = strings.tmp.tmp; size_t tmp_buf_size = sizeof(strings.tmp.tmp); - size_t off; const char *review_title; const char *sign_title; nbgl_contentTagValue_t *pairs; s_field_table_entry entry; bool show_network; - nbgl_tipBox_t tip_box; + nbgl_contentValueExt_t *ext; + nbgl_contentInfoList_t *infolist; const void *mem_before = mem_alloc(0); + explicit_bzero(&warning, sizeof(nbgl_warning_t)); +#ifdef HAVE_WEB3_CHECKS + set_tx_simulation_warning(&warning, true, true); +#endif + snprintf(tmp_buf, tmp_buf_size, "Review transaction to %s", get_operation_type()); if ((review_title = _strdup(tmp_buf)) == NULL) { return cleanup_on_error(mem_before); } - snprintf(tmp_buf, tmp_buf_size, "Sign transaction to %s?", get_operation_type()); + snprintf(tmp_buf, + tmp_buf_size, + "%s transaction to %s?", + ui_tx_simulation_finish_str(), + get_operation_type()); if ((sign_title = _strdup(tmp_buf)) == NULL) { return cleanup_on_error(mem_before); } - explicit_bzero(&tip_box, sizeof(tip_box)); - tip_box.icon = &C_review_info_button; - tip_box.text = NULL; - tip_box.modalTitle = "Contract information"; - tip_box.type = INFOS_LIST; - if (!prepare_infos(&tip_box.infos)) { - return cleanup_on_error(mem_before); - } - snprintf(tmp_buf, tmp_buf_size, "Interaction with a\nsmart contract"); - off = strlen(tmp_buf); - if (get_creator_name()) { - snprintf(tmp_buf + off, tmp_buf_size - off, " from:\n%s", get_creator_name()); - } - if ((tip_box.text = _strdup(tmp_buf)) == NULL) { - return cleanup_on_error(mem_before); - } - g_pair_list.nbPairs = field_table_size() + 1; + explicit_bzero(&g_pair_list, sizeof(g_pair_list)); + // Contract info + g_pair_list.nbPairs += 1; + // TX fields + g_pair_list.nbPairs += field_table_size(); show_network = get_tx_chain_id() != chainConfig->chainId; if (show_network) { g_pair_list.nbPairs += 1; } + // Fees + g_pair_list.nbPairs += 1; + if ((pairs = mem_alloc_and_align(sizeof(*pairs) * g_pair_list.nbPairs, __alignof__(*pairs))) == NULL) { return cleanup_on_error(mem_before); } explicit_bzero(pairs, sizeof(*pairs) * g_pair_list.nbPairs); + pairs[0].item = _strdup("Interaction with"); + pairs[0].value = get_creator_name(); + if (pairs[0].value == NULL) { + // not great, but this cannot be NULL + pairs[0].value = _strdup("a smart contract"); + } + if ((ext = mem_alloc_and_align(sizeof(*ext), __alignof__(*ext))) == NULL) { + return cleanup_on_error(mem_before); + } + explicit_bzero(ext, sizeof(*ext)); + if ((infolist = mem_alloc_and_align(sizeof(*infolist), __alignof__(*infolist))) == NULL) { + return cleanup_on_error(mem_before); + } + if (!prepare_infos(infolist)) { + return cleanup_on_error(mem_before); + } + ext->infolist = infolist; + ext->aliasType = INFO_LIST_ALIAS; + if ((ext->backText = get_creator_name()) == NULL) { + ext->backText = _strdup("Smart contract information"); + } + pairs[0].extension = ext; + pairs[0].aliasValue = 1; + for (int i = 0; i < (int) field_table_size(); ++i) { if (!get_from_field_table(i, &entry)) { return cleanup_on_error(mem_before); } - pairs[i].item = entry.key; - pairs[i].value = entry.value; + pairs[1 + i].item = entry.key; + pairs[1 + i].value = entry.value; } if (show_network) { @@ -214,15 +239,16 @@ bool ui_gcs(void) { PRINTF("Error: Could not format the max fees!\n"); } pairs[g_pair_list.nbPairs - 1].value = _strdup(tmp_buf); - g_pair_list.pairs = pairs; + nbgl_useCaseAdvancedReview(TYPE_TRANSACTION, &g_pair_list, get_tx_icon(), review_title, NULL, sign_title, - &tip_box, + NULL, + &warning, review_choice); g_alloc_size = mem_alloc(0) - mem_before; return true; diff --git a/src_nbgl/ui_get_eth2_public_key.c b/src_nbgl/ui_get_eth2_public_key.c index e9b2ded0f9..2058d98067 100644 --- a/src_nbgl/ui_get_eth2_public_key.c +++ b/src_nbgl/ui_get_eth2_public_key.c @@ -1,8 +1,5 @@ -#include -#include "shared_context.h" #include "ui_callbacks.h" #include "ui_nbgl.h" -#include "uint_common.h" static void reviewChoice(bool confirm) { if (confirm) { diff --git a/src_nbgl/ui_get_public_key.c b/src_nbgl/ui_get_public_key.c index bcaccfb78e..f1f6a06d29 100644 --- a/src_nbgl/ui_get_public_key.c +++ b/src_nbgl/ui_get_public_key.c @@ -1,4 +1,3 @@ -#include "nbgl_use_case.h" #include "shared_context.h" #include "ui_callbacks.h" #include "ui_nbgl.h" diff --git a/src_nbgl/ui_home.c b/src_nbgl/ui_home.c index 9eaf38fb9a..119472ec87 100644 --- a/src_nbgl/ui_home.c +++ b/src_nbgl/ui_home.c @@ -1,8 +1,10 @@ -#include "common_ui.h" #include "ui_nbgl.h" -#include "nbgl_use_case.h" #include "caller_api.h" #include "network.h" +#include "cmd_get_tx_simulation.h" + +// Global Warning struct for NBGL review flows +nbgl_warning_t warning; // settings info definition #define SETTING_INFO_NB 2 @@ -14,7 +16,8 @@ #define FORMAT_PLUGIN "This app enables clear\nsigning transactions for\nthe %s dApp." enum { - BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, + WEB3_CHECK_TOKEN = FIRST_USER_TOKEN, + BLIND_SIGNING_TOKEN, #ifdef HAVE_TRUSTED_NAME TRUSTED_NAME_VERBOSE_TOKEN, #endif @@ -26,6 +29,9 @@ enum { }; enum { +#ifdef HAVE_WEB3_CHECKS + WEB3_CHECK_ID, +#endif BLIND_SIGNING_ID, #ifdef HAVE_TRUSTED_NAME TRUSTED_NAME_VERBOSE_ID, @@ -56,6 +62,14 @@ static void setting_toggle_callback(int token, uint8_t index, int page) { bool value; switch (token) { +#ifdef HAVE_WEB3_CHECKS + case WEB3_CHECK_TOKEN: + handle_tx_simulation_opt_in(false); + value = !N_storage.w3c_enable; + switches[WEB3_CHECK_ID].initState = (nbgl_state_t) value; + nvm_write((void *) &N_storage.w3c_enable, (void *) &value, sizeof(value)); + break; +#endif // HAVE_WEB3_CHECKS case BLIND_SIGNING_TOKEN: value = !N_storage.dataAllowed; switches[BLIND_SIGNING_ID].initState = (nbgl_state_t) value; @@ -152,6 +166,15 @@ static void prepare_and_display_home(const char *appname, const char *tagline, u switches[DEBUG_ID].token = DEBUG_TOKEN; switches[DEBUG_ID].tuneId = TUNE_TAP_CASUAL; +#ifdef HAVE_WEB3_CHECKS + switches[WEB3_CHECK_ID].initState = N_storage.w3c_enable ? ON_STATE : OFF_STATE; + switches[WEB3_CHECK_ID].text = "Transaction Check"; + switches[WEB3_CHECK_ID].subText = + "Get real-time warnings about risky transactions. Learn more: ledger.com/tx-check"; + switches[WEB3_CHECK_ID].token = WEB3_CHECK_TOKEN; + switches[WEB3_CHECK_ID].tuneId = TUNE_TAP_CASUAL; +#endif // HAVE_WEB3_CHECKS + contents[0].type = SWITCHES_LIST; contents[0].content.switchesList.nbSwitches = SETTINGS_SWITCHES_NB; contents[0].content.switchesList.switches = switches; diff --git a/src_nbgl/ui_message_signing.h b/src_nbgl/ui_message_signing.h index 8c8c193b7d..c20d4ef5f2 100644 --- a/src_nbgl/ui_message_signing.h +++ b/src_nbgl/ui_message_signing.h @@ -2,13 +2,6 @@ #define UI_MESSAGE_SIGNING_H_ #include -#include "ui_signing.h" - -#define TEXT_MESSAGE "message" -#define TEXT_TYPED_MESSAGE "typed " TEXT_MESSAGE -#define TEXT_REVIEW_EIP712 REVIEW(TEXT_TYPED_MESSAGE) -#define TEXT_SIGN_EIP712 SIGN(TEXT_TYPED_MESSAGE) -#define TEXT_BLIND_SIGN_EIP712 BLIND_SIGN(TEXT_TYPED_MESSAGE) void ui_typed_message_review_choice_v0(bool confirm); #ifdef HAVE_EIP712_FULL_SUPPORT diff --git a/src_nbgl/ui_nbgl.h b/src_nbgl/ui_nbgl.h index ad07dc31cc..271f7591a3 100644 --- a/src_nbgl/ui_nbgl.h +++ b/src_nbgl/ui_nbgl.h @@ -1,18 +1,27 @@ #ifndef _UI_NBGL_H_ #define _UI_NBGL_H_ -#include -#include -#include +#include "nbgl_use_case.h" +#include "shared_context.h" +#include "glyphs.h" + +#ifdef SCREEN_SIZE_WALLET +#define ICON_APP_WARNING C_Warning_64px +#define ICON_APP_REVIEW C_Review_64px +#else +#define ICON_APP_WARNING C_icon_warning +#define ICON_APP_REVIEW C_icon_certificate +#endif #define SHARED_BUFFER_SIZE SHARED_CTX_FIELD_1_SIZE extern char g_stax_shared_buffer[SHARED_BUFFER_SIZE]; -extern nbgl_page_t* pageContext; - const nbgl_icon_details_t* get_app_icon(bool caller_icon); const nbgl_icon_details_t* get_tx_icon(void); +// Global Warning struct for NBGL review flows +extern nbgl_warning_t warning; + void ui_idle(void); void ui_settings(void); diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c index cd4afcf90b..2503aefbb9 100644 --- a/src_nbgl/ui_sign_712.c +++ b/src_nbgl/ui_sign_712.c @@ -1,20 +1,16 @@ #ifdef HAVE_EIP712_FULL_SUPPORT -#include // explicit_bzero #include "common_ui.h" #include "ui_nbgl.h" #include "ui_logic.h" -#include "common_712.h" -#include "nbgl_use_case.h" #include "ui_message_signing.h" -#include "ledger_assert.h" -#include "apdu_constants.h" +#include "cmd_get_tx_simulation.h" +#include "utils.h" static nbgl_contentTagValue_t pairs[7]; static nbgl_contentTagValueList_t pairs_list; static uint8_t pair_idx; static size_t buf_idx; -static bool filtered; static bool review_skipped; static void message_progress(bool confirm) { @@ -53,6 +49,7 @@ static void message_update(bool confirm) { size_t buf_size; size_t buf_off; bool flag; + bool skippable; buf = get_ui_pairs_buffer(&buf_size); if (confirm) { @@ -66,8 +63,9 @@ static void message_update(bool confirm) { pairs[pair_idx].value = memmove(buf + buf_idx, strings.tmp.tmp, buf_off); buf_idx += buf_off; pair_idx += 1; + skippable = warning.predefinedSet & SET_BIT(BLIND_SIGNING_WARN); pairs_list.nbPairs = - nbgl_useCaseGetNbTagValuesInPageExt(pair_idx, &pairs_list, 0, !filtered, &flag); + nbgl_useCaseGetNbTagValuesInPageExt(pair_idx, &pairs_list, 0, skippable, &flag); } if (!review_skipped && ((pair_idx == ARRAYLEN(pairs)) || (pairs_list.nbPairs < pair_idx))) { nbgl_useCaseReviewStreamingContinueExt(&pairs_list, message_progress, review_skip); @@ -79,46 +77,90 @@ static void message_update(bool confirm) { } } -static void ui_712_start_common(bool has_filtering) { +static void ui_712_start_common(void) { explicit_bzero(&pairs, sizeof(pairs)); explicit_bzero(&pairs_list, sizeof(pairs_list)); pairs_list.pairs = pairs; pair_idx = 0; buf_idx = 0; - filtered = has_filtering; review_skipped = false; + if (appState != APP_STATE_IDLE) { + reset_app_context(); + } + appState = APP_STATE_SIGNING_EIP712; + explicit_bzero(&warning, sizeof(nbgl_warning_t)); +#ifdef HAVE_WEB3_CHECKS + set_tx_simulation_warning(&warning, false, false); +#endif } void ui_712_start_unfiltered(void) { - ui_712_start_common(false); - nbgl_useCaseReviewStreamingBlindSigningStart(TYPE_MESSAGE | SKIPPABLE_OPERATION, - &C_Review_64px, - TEXT_REVIEW_EIP712, - NULL, - message_update); + 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); } void ui_712_start(void) { - ui_712_start_common(true); - nbgl_useCaseReviewStreamingStart(TYPE_MESSAGE, - &C_Review_64px, - TEXT_REVIEW_EIP712, - NULL, - message_update); + 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); + } } void ui_712_switch_to_message(void) { message_update(true); } +#ifdef HAVE_WEB3_CHECKS +static void ui_712_w3c_cb(bool confirm) { + if (confirm) { + // User has clicked on "Reject transaction" + ui_typed_message_review_choice(false); + } else { + // User has clicked on "Sign anyway" + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "%s typed message?", + ui_tx_simulation_finish_str()); + nbgl_useCaseReviewStreamingFinish(g_stax_shared_buffer, ui_typed_message_review_choice); + } +} +#endif + void ui_712_switch_to_sign(void) { if (!review_skipped && (pair_idx > 0)) { pairs_list.nbPairs = pair_idx; pair_idx = 0; nbgl_useCaseReviewStreamingContinueExt(&pairs_list, message_progress, review_skip); } else { - nbgl_useCaseReviewStreamingFinish(filtered ? TEXT_SIGN_EIP712 : TEXT_BLIND_SIGN_EIP712, - ui_typed_message_review_choice); +#ifdef HAVE_WEB3_CHECKS + if ((TX_SIMULATION.risk != RISK_UNKNOWN) && ((check_tx_simulation_hash() == false) || + check_tx_simulation_from_address() == false)) { + ui_tx_simulation_error(ui_712_w3c_cb); + return; + } +#endif + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "%s typed message?", + ui_tx_simulation_finish_str()); + nbgl_useCaseReviewStreamingFinish(g_stax_shared_buffer, ui_typed_message_review_choice); } } diff --git a/src_nbgl/ui_sign_712_v0.c b/src_nbgl/ui_sign_712_v0.c index 64bc640f59..213ad781e0 100644 --- a/src_nbgl/ui_sign_712_v0.c +++ b/src_nbgl/ui_sign_712_v0.c @@ -1,9 +1,8 @@ -#include // explicit_bzero -#include "os_utils.h" // ARRAYLEN -#include "common_ui.h" #include "ui_nbgl.h" #include "common_712.h" #include "ui_message_signing.h" +#include "cmd_get_tx_simulation.h" +#include "utils.h" static nbgl_contentTagValue_t pairs[2]; static nbgl_contentTagValueList_t pairs_list; @@ -32,12 +31,27 @@ void ui_sign_712_v0(void) { pairs_list.pairs = pairs; pairs_list.nbMaxLinesForValue = 0; - nbgl_useCaseReviewBlindSigning(TYPE_TRANSACTION, - &pairs_list, - &C_Review_64px, - TEXT_REVIEW_EIP712, - NULL, - TEXT_BLIND_SIGN_EIP712, - NULL, - ui_typed_message_review_choice_v0); + if (appState != APP_STATE_IDLE) { + reset_app_context(); + } + appState = APP_STATE_SIGNING_EIP712; + explicit_bzero(&warning, sizeof(nbgl_warning_t)); +#ifdef HAVE_WEB3_CHECKS + set_tx_simulation_warning(&warning, true, true); +#endif + warning.predefinedSet |= SET_BIT(BLIND_SIGNING_WARN); + + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "%s typed message?", + ui_tx_simulation_finish_str()); + nbgl_useCaseAdvancedReview(TYPE_TRANSACTION, + &pairs_list, + &ICON_APP_REVIEW, + "Review typed message", + NULL, + g_stax_shared_buffer, + 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 efabd82d2a..e008a79852 100644 --- a/src_nbgl/ui_sign_message.c +++ b/src_nbgl/ui_sign_message.c @@ -1,16 +1,11 @@ -#include "nbgl_page.h" -#include "shared_context.h" #include "ui_callbacks.h" #include "ui_nbgl.h" #include "sign_message.h" -#include "glyphs.h" -#include "nbgl_use_case.h" -#include "common_ui.h" #include "ui_message_signing.h" -#include "ui_signing.h" +#include "cmd_get_tx_simulation.h" -#define TEXT_REVIEW_EIP191 REVIEW(TEXT_MESSAGE) -#define TEXT_SIGN_EIP191 SIGN(TEXT_MESSAGE) +// TODO Re-activate when partners are ready for eip191 +#undef HAVE_WEB3_CHECKS typedef enum { UI_191_ACTION_IDLE = 0, @@ -50,11 +45,11 @@ static bool ui_191_update_display_buffer(void) { g_stax_shared_buffer[g_display_buffer_idx] = '\0'; strlcat(g_stax_shared_buffer + g_display_buffer_idx, - strings.tmp.tmp + g_rcv_buffer_idx, + UI_191_BUFFER + g_rcv_buffer_idx, sizeof(g_stax_shared_buffer) - g_display_buffer_idx); reached = nbgl_getTextMaxLenInNbLines(LARGE_MEDIUM_FONT, (char *) g_stax_shared_buffer, - SCREEN_WIDTH - (2 * BORDER_MARGIN), + AVAILABLE_WIDTH, NB_MAX_LINES_IN_REVIEW, &len, false); @@ -91,6 +86,22 @@ static void ui_191_show_message(void) { nbgl_useCaseReviewStreamingContinueExt(&pairs_list, ui_191_data_cb, ui_191_skip_cb); } +#ifdef HAVE_WEB3_CHECKS +static void ui_191_w3c_cb(bool confirm) { + if (confirm) { + // User has clicked on "Reject transaction" + ui_191_finish_cb(false); + } else { + // User has clicked on "Sign anyway" + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "%s message?", + ui_tx_simulation_finish_str()); + nbgl_useCaseReviewStreamingFinish(g_stax_shared_buffer, ui_191_finish_cb); + } +} +#endif + static void ui_191_process_state(void) { switch (g_action) { case UI_191_ACTION_IDLE: @@ -102,7 +113,19 @@ static void ui_191_process_state(void) { } break; case UI_191_ACTION_GO_TO_SIGN: - nbgl_useCaseReviewStreamingFinish(TEXT_SIGN_EIP191, ui_191_finish_cb); +#ifdef HAVE_WEB3_CHECKS + if ((TX_SIMULATION.risk != RISK_UNKNOWN) && + ((check_tx_simulation_hash() == false) || + check_tx_simulation_from_address() == false)) { + ui_tx_simulation_error(ui_191_w3c_cb); + return; + } +#endif + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "%s message?", + ui_tx_simulation_finish_str()); + nbgl_useCaseReviewStreamingFinish(g_stax_shared_buffer, ui_191_finish_cb); break; } } @@ -113,11 +136,24 @@ void ui_191_start(void) { g_rcv_buffer_idx = 0; g_skipped = false; - nbgl_useCaseReviewStreamingStart(TYPE_MESSAGE | SKIPPABLE_OPERATION, - &C_Review_64px, - TEXT_REVIEW_EIP191, - NULL, - ui_191_data_cb); + explicit_bzero(&warning, sizeof(nbgl_warning_t)); +#ifdef HAVE_WEB3_CHECKS + set_tx_simulation_warning(&warning, false, true); +#endif + if (warning.predefinedSet == 0) { + nbgl_useCaseReviewStreamingStart(TYPE_MESSAGE | SKIPPABLE_OPERATION, + &ICON_APP_REVIEW, + "Review message", + NULL, + ui_191_data_cb); + } else { + nbgl_useCaseAdvancedReviewStreamingStart(TYPE_MESSAGE | SKIPPABLE_OPERATION, + &ICON_APP_REVIEW, + "Review message", + NULL, + &warning, + ui_191_data_cb); + } } void ui_191_switch_to_message(void) { @@ -128,7 +164,7 @@ void ui_191_switch_to_message(void) { void ui_191_switch_to_sign(void) { g_action = UI_191_ACTION_GO_TO_SIGN; if (g_skipped) { - nbgl_useCaseReviewStreamingFinish(TEXT_SIGN_EIP191, ui_191_finish_cb); + ui_191_process_state(); } else if (g_display_buffer_idx > 0) { // still on an incomplete display buffer, show it before the last page ui_191_show_message(); diff --git a/src_nbgl/ui_signing.c b/src_nbgl/ui_signing.c deleted file mode 100644 index 2becdf07de..0000000000 --- a/src_nbgl/ui_signing.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "ui_signing.h" - -e_ui_signing_position g_position; diff --git a/src_nbgl/ui_signing.h b/src_nbgl/ui_signing.h deleted file mode 100644 index 6595f10664..0000000000 --- a/src_nbgl/ui_signing.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef UI_SIGNING_H_ -#define UI_SIGNING_H_ - -#define SIGN_BUTTON "Hold to sign" -#define REJECT_BUTTON "Reject" -#define SIGN(msg) "Sign " msg "?" -#define BLIND_SIGN(msg) "Accept risk and sign " msg "?" -#define REVIEW(msg) "Review " msg -#define REJECT(msg) "Reject " msg -#define REJECT_QUESTION(msg) REJECT(msg) "?" -#define REJECT_CONFIRM_BUTTON "Yes, reject" -#define RESUME(msg) "Go back to " msg - -typedef enum { - UI_SIGNING_POSITION_START = 0, - UI_SIGNING_POSITION_REVIEW, - UI_SIGNING_POSITION_SIGN -} e_ui_signing_position; - -extern e_ui_signing_position g_position; - -#endif // UI_SIGNING_H_ diff --git a/src_nbgl/ui_tx_simulation.c b/src_nbgl/ui_tx_simulation.c new file mode 100644 index 0000000000..e220d4f2d8 --- /dev/null +++ b/src_nbgl/ui_tx_simulation.c @@ -0,0 +1,205 @@ +#ifdef HAVE_NBGL +#ifdef HAVE_WEB3_CHECKS + +#include "apdu_constants.h" +#include "utils.h" +#include "nbgl_use_case.h" +#include "glyphs.h" +#include "ui_nbgl.h" +#include "ui_callbacks.h" +#include "ui_callbacks.h" +#include "cmd_get_tx_simulation.h" + +#define HOW_TO_INFO_NB 3 + +enum { + WARNING_CHOICE_TOKEN = FIRST_USER_TOKEN, + WARNING_BUTTON_TOKEN, + DISMISS_WARNING_TOKEN, +}; + +// 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) { + 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 + * + * @param[in] token Id of the pressed widget (button) + * @param[in] index Indicates the value of the pressed button + */ +static void opt_in_explain_cb(int token, uint8_t index) { + UNUSED(token); + UNUSED(index); + ui_tx_simulation_opt_in(g_response_expected); +} + +/** + * @brief Display the "How it works" screen + * + */ +static void ui_tx_simulation_explain(void) { + nbgl_layout_t *layoutCtx = NULL; + nbgl_layoutDescription_t layoutDescription = {0}; + nbgl_layoutLeftContent_t info = {0}; + nbgl_layoutHeader_t headerDesc = {.type = HEADER_BACK_AND_TEXT, + .backAndText.tuneId = TUNE_TAP_CASUAL, + .backAndText.token = DISMISS_WARNING_TOKEN}; + + layoutDescription.withLeftBorder = true; + layoutDescription.onActionCallback = opt_in_explain_cb; + layoutCtx = nbgl_layoutGet(&layoutDescription); + const char *rowTexts[HOW_TO_INFO_NB] = { + "Transaction is checked for threats before signing.", + "The result is displayed: Critical threat, potential risk or no threat.", + "Scan the QR Code on your Ledger device for details on any threat or risk.", + }; + const nbgl_icon_details_t *rowIcons[HOW_TO_INFO_NB] = { + &PRIVACY_ICON, + &WARNING_ICON, + &QRCODE_ICON, + }; + + // add header + nbgl_layoutAddHeader(layoutCtx, &headerDesc); + + // add title + info.title = "How it works"; + info.nbRows = HOW_TO_INFO_NB; + info.rowTexts = rowTexts; + info.rowIcons = rowIcons; + nbgl_layoutAddLeftContent(layoutCtx, &info); + + nbgl_layoutDraw(layoutCtx); + nbgl_refresh(); +} + +/** + * @brief Finalise the opt-in process with status + * + * @param[in] confirm Flag indicates if the user validates the setting + * @param[in] callback Callback to display the next screen + */ +static void finalise_opt_in(bool confirm, nbgl_callback_t callback) { + if (confirm) { + nbgl_useCaseStatus("Transaction Check enabled", true, callback); + } else { + callback(); + } +} + +/** + * @brief Callback called when user press a button on the opt-in screen + * + * @param[in] token Id of the pressed widget (button) + * @param[in] index Indicates the value of the pressed button + */ +static void opt_in_action_cb(int token, uint8_t index) { + bool opt_in = true; + bool confirm = true; + + switch (token) { + case WARNING_CHOICE_TOKEN: + // Set the opt-in flag + nvm_write((void *) &N_storage.w3c_opt_in, (void *) &opt_in, sizeof(opt_in)); + confirm = (index == 0 ? true : false); + if (confirm != N_storage.w3c_enable) { + // Set the Web3 Check flag + nvm_write((void *) &N_storage.w3c_enable, (void *) &confirm, sizeof(confirm)); + } + if (g_response_expected) { + // just respond the current state and return to idle screen + G_io_apdu_buffer[0] = N_storage.w3c_enable; + io_seproxyhal_send_status(APDU_RESPONSE_OK, 1, false, false); + finalise_opt_in(confirm, ui_idle); + } else { + finalise_opt_in(confirm, ui_settings); + } + break; + case WARNING_BUTTON_TOKEN: + ui_tx_simulation_explain(); + break; + default: + break; + } +} + +/** + * @brief Display the opt-in screen + * + * @param[in] response_expected indicates if a RAPDU is expected + */ +void ui_tx_simulation_opt_in(bool response_expected) { + nbgl_layout_t *layoutCtx = NULL; + nbgl_layoutDescription_t layoutDescription = {0}; + nbgl_contentCenter_t info = {0}; + nbgl_layoutChoiceButtons_t buttonsInfo = {.topText = "Yes, enable", + .bottomText = "Maybe later", + .token = WARNING_CHOICE_TOKEN, + .style = ROUNDED_AND_FOOTER_STYLE, + .tuneId = TUNE_TAP_CASUAL}; + + nbgl_layoutHeader_t headerDesc = {.type = HEADER_EXTENDED_BACK, + .separationLine = false, + .extendedBack.actionIcon = &QUESTION_CIRCLE_ICON, + .extendedBack.backToken = NBGL_INVALID_TOKEN, + .extendedBack.tuneId = TUNE_TAP_CASUAL, + .extendedBack.text = NULL, + .extendedBack.actionToken = WARNING_BUTTON_TOKEN}; + + g_response_expected = response_expected; + layoutDescription.withLeftBorder = true; + layoutDescription.onActionCallback = opt_in_action_cb; + layoutCtx = nbgl_layoutGet(&layoutDescription); + + // add header + nbgl_layoutAddHeader(layoutCtx, &headerDesc); + + // add main content + info.title = "Enable\nTransaction Check?"; + info.description = + "Get real-time warnings about risky Ethereum transactions. " + "Powered by service providers."; + info.subText = "By enabling, you accept T&Cs: ledger.com/tx-check"; + nbgl_layoutAddContentCenter(layoutCtx, &info); + + // add button and footer on bottom + nbgl_layoutAddChoiceButtons(layoutCtx, &buttonsInfo); + + nbgl_layoutDraw(layoutCtx); + nbgl_refresh(); +} + +#endif // HAVE_WEB3_CHECKS + +/** + * @brief Determine the Review finish title prefix. + * + * @return Finish title prefix string + */ +const char *ui_tx_simulation_finish_str(void) { + if (warning.predefinedSet & SET_BIT(W3C_THREAT_DETECTED_WARN)) { + return "Accept threat and sign"; + } + if ((warning.predefinedSet & SET_BIT(W3C_RISK_DETECTED_WARN)) || + (warning.predefinedSet & SET_BIT(BLIND_SIGNING_WARN))) { + return "Accept risk and sign"; + } + return "Sign"; +} + +#endif // HAVE_NBGL diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt index 8ef8e50817..88499847fd 100644 --- a/tests/fuzzing/CMakeLists.txt +++ b/tests/fuzzing/CMakeLists.txt @@ -24,9 +24,12 @@ if (NOT DEFINED BOLOS_SDK) set(BOLOS_SDK /opt/${TARGET_DEVICE}-secure-sdk) endif() +# some flags to mimic the embedded build (such as packed enums) +set(CUSTOM_C_FLAGS -fdata-sections -ffunction-sections -funsigned-char -fshort-enums) + # compatible with ClusterFuzzLite if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) - set(COMPILATION_FLAGS -g -O0 -Wall -Wextra -fprofile-instr-generate -fcoverage-mapping) + set(COMPILATION_FLAGS ${CUSTOM_C_FLAGS} -g -O0 -Wall -Wextra -fprofile-instr-generate -fcoverage-mapping) if (SANITIZER MATCHES "address") set(COMPILATION_FLAGS ${COMPILATION_FLAGS} -fsanitize=fuzzer,address,undefined) elseif (SANITIZER MATCHES "memory") @@ -35,7 +38,7 @@ if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) message(FATAL_ERROR "Unkown sanitizer type. It must be set to `address` or `memory`.") endif() else() - set(COMPILATION_FLAGS "$ENV{LIB_FUZZING_ENGINE} $ENV{CFLAGS}") + set(COMPILATION_FLAGS "$ENV{LIB_FUZZING_ENGINE} $ENV{CFLAGS} ${CUSTOM_C_FLAGS}") separate_arguments(COMPILATION_FLAGS) endif() @@ -155,6 +158,7 @@ set(DEFINES HAVE_ENUM_VALUE HAVE_NFT_SUPPORT HAVE_DYNAMIC_NETWORKS + HAVE_WEB3_CHECKS explicit_bzero=bzero # Fix for https://github.com/google/sanitizers/issues/1507 ) @@ -179,11 +183,13 @@ include_directories( ${CMAKE_SOURCE_DIR}/../../src ${CMAKE_SOURCE_DIR}/../../src_features/generic_tx_parser/ ${CMAKE_SOURCE_DIR}/../../src_features/provide_enum_value/ - ${CMAKE_SOURCE_DIR}/../../src_features/provideDynamicNetwork/ + ${CMAKE_SOURCE_DIR}/../../src_features/provide_network_info/ ${CMAKE_SOURCE_DIR}/../../src_features/signTx/ - ${CMAKE_SOURCE_DIR}/../../src_features/provideTrustedName/ + ${CMAKE_SOURCE_DIR}/../../src_features/provide_trusted_name/ ${CMAKE_SOURCE_DIR}/../../src_features/getChallenge/ ${CMAKE_SOURCE_DIR}/../../src_features/signMessageEIP712/ + ${CMAKE_SOURCE_DIR}/../../src_features/provide_proxy_info/ + ${CMAKE_SOURCE_DIR}/../../src_features/provide_tx_simulation/ ${BOLOS_SDK}/include ${BOLOS_SDK}/target/${TARGET_DEVICE}/include ${BOLOS_SDK}/lib_cxng/include @@ -196,11 +202,13 @@ include_directories( FILE(GLOB_RECURSE SOURCES ${CMAKE_SOURCE_DIR}/../../src_features/generic_tx_parser/*.c - ${CMAKE_SOURCE_DIR}/../../src_features/provideTrustedName/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provide_trusted_name/*.c ${CMAKE_SOURCE_DIR}/../../src_features/getChallenge/*.c ${CMAKE_SOURCE_DIR}/../../src_features/provide_enum_value/*.c - ${CMAKE_SOURCE_DIR}/../../src_features/provideDynamicNetwork/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provide_network_info/*.c ${CMAKE_SOURCE_DIR}/../../src_features/provideNFTInformation/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provide_proxy_info/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provide_tx_simulation/*.c ${CMAKE_SOURCE_DIR}/../../src/mem.c ${CMAKE_SOURCE_DIR}/../../src/mem_utils.c ${CMAKE_SOURCE_DIR}/../../src/network.c diff --git a/tests/fuzzing/src/fuzzer.c b/tests/fuzzing/src/fuzzer.c index 3b024c80ba..4fde4d5d9c 100644 --- a/tests/fuzzing/src/fuzzer.c +++ b/tests/fuzzing/src/fuzzer.c @@ -1,7 +1,13 @@ #include #include -#include "network_dynamic.h" +#include "cmd_trusted_name.h" + +#include "cmd_network_info.h" + +#include "cmd_get_tx_simulation.h" + +#include "cmd_proxy_info.h" #include "cmd_field.h" #include "cmd_tx_info.h" @@ -13,6 +19,7 @@ #include "shared_context.h" #include "tlv.h" +#include "mem.h" #include "apdu_constants.h" // Fuzzing harness interface @@ -32,6 +39,7 @@ const chain_config_t *chainConfig = &config; uint8_t appState; tmpCtx_t tmpCtx; strings_t strings; +const internalStorage_t N_storage_real = {.w3c_enable = true, .w3c_opt_in = true}; int fuzzGenericParserFieldCmd(const uint8_t *data, size_t size) { s_field field = {0}; @@ -76,8 +84,7 @@ int fuzzDynamicNetworks(const uint8_t *data, size_t size) { p2 = data[offset++]; len = data[offset++]; if (size - offset < len) return 0; - if (handleNetworkConfiguration(p1, p2, data + offset, len, &tx) != APDU_RESPONSE_OK) - return 1; + if (handle_network_info(p1, p2, data + offset, len, &tx) != APDU_RESPONSE_OK) return 1; offset += len; } return 0; @@ -93,7 +100,7 @@ int fuzzTrustedNames(const uint8_t *data, size_t size) { p1 = data[offset++]; len = data[offset++]; if (size - offset < len) return 0; - if (handle_provide_trusted_name(p1, data + offset, len) != APDU_RESPONSE_OK) return 1; + if (handle_trusted_name(p1, data + offset, len) != APDU_RESPONSE_OK) return 1; offset += len; } return 0; @@ -104,6 +111,55 @@ int fuzzNFTInfo(const uint8_t *data, size_t size) { return handleProvideNFTInformation(data, size, &tx) != APDU_RESPONSE_OK; } +int fuzzProxyInfo(const uint8_t *data, size_t size) { + if (size < 1) return 0; + return handle_proxy_info(data[0], 0, size - 1, data + 1); +} + +int fuzzTxSimulation(const uint8_t *data, size_t size) { + unsigned int flags; + if (size < 2) return 0; + + if (handle_tx_simulation(data[0], data[1], data + 2, size - 2, &flags) != APDU_RESPONSE_OK) + return 1; + + get_tx_simulation_risk_str(); + get_tx_simulation_category_str(); + return 0; +} + +int fuzzCalldata(const uint8_t *data, size_t size) { + while (size > 0) { + switch (data[0]) { + case 'I': + data++; + size--; + mem_reset(); + calldata_init(500); + break; + case 'W': + size--; + data++; + if (size < 1 || size < data[0] + 1) return 0; + calldata_append(data + 1, data[0]); + size -= (1 + data[0]); + data += 1 + data[0]; + break; + case 'R': + size--; + data++; + if (size < 1) return 0; + calldata_get_chunk(data[0]); + size--; + data++; + break; + default: + return 0; + } + } + return 0; +} + // Array of fuzzing harness functions harness harnesses[] = { fuzzGenericParserFieldCmd, @@ -112,6 +168,9 @@ harness harnesses[] = { fuzzDynamicNetworks, fuzzTrustedNames, fuzzNFTInfo, + fuzzProxyInfo, + fuzzTxSimulation, + fuzzCalldata, }; /* Main fuzzing handler called by libfuzzer */ @@ -125,6 +184,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { explicit_bzero(&G_io_apdu_buffer, 260); explicit_bzero(&sha3, sizeof(sha3)); + calldata_cleanup(); + mem_reset(); + uint8_t target; txContext.content = &txContent; diff --git a/tests/fuzzing/src/mock.c b/tests/fuzzing/src/mock.c index cfcd65c831..d08a28cae2 100644 --- a/tests/fuzzing/src/mock.c +++ b/tests/fuzzing/src/mock.c @@ -4,6 +4,8 @@ #include "cx_errors.h" #include "cx_sha256.h" #include "cx_sha3.h" +#include "buffer.h" +#include "lcx_ecfp.h" /** MemorySanitizer does not wrap explicit_bzero https://github.com/google/sanitizers/issues/1507 * which results in false positives when running MemorySanitizer. @@ -167,3 +169,31 @@ size_t cx_hash_sha256(const uint8_t *in, size_t in_len, uint8_t *out, size_t out if (in_len > 0 && out_len > 0) out[out_len - 1] = in[in_len - 1]; return CX_OK; } + +typedef unsigned char bolos_task_status_t; + +void os_sched_exit(__attribute__((unused)) bolos_task_status_t exit_code) { + return; +} + +int io_send_response_buffers(const buffer_t *rdatalist, size_t count, uint16_t sw) { + UNUSED(rdatalist); + UNUSED(count); + UNUSED(sw); + return 0; +} + +uint16_t io_seproxyhal_send_status(uint16_t sw, uint32_t tx, bool reset, bool idle) { + return 0; +} + +uint32_t os_pki_get_info(uint8_t *key_usage, + uint8_t *trusted_name, + size_t *trusted_name_len, + cx_ecfp_384_public_key_t *public_key) { + memcpy(trusted_name, "trusted name", sizeof("trusted name")); + return 0; +} + +void ui_tx_simulation_opt_in(bool response_expected) { +} diff --git a/tests/ragger/abis/proxy_implem.abi.json b/tests/ragger/abis/proxy_implem.abi.json new file mode 100644 index 0000000000..f518868a9f --- /dev/null +++ b/tests/ragger/abis/proxy_implem.abi.json @@ -0,0 +1,1747 @@ +[ + { + "inputs" : [ + { + "internalType" : "contract IStrategyManager", + "name" : "_strategyManager", + "type" : "address" + }, + { + "internalType" : "contract ISlasher", + "name" : "_slasher", + "type" : "address" + }, + { + "internalType" : "contract IEigenPodManager", + "name" : "_eigenPodManager", + "type" : "address" + } + ], + "stateMutability" : "nonpayable", + "type" : "constructor" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "internalType" : "uint8", + "name" : "version", + "type" : "uint8" + } + ], + "name" : "Initialized", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "internalType" : "uint256", + "name" : "previousValue", + "type" : "uint256" + }, + { + "indexed" : false, + "internalType" : "uint256", + "name" : "newValue", + "type" : "uint256" + } + ], + "name" : "MinWithdrawalDelayBlocksSet", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "components" : [ + { + "internalType" : "address", + "name" : "earningsReceiver", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegationApprover", + "type" : "address" + }, + { + "internalType" : "uint32", + "name" : "stakerOptOutWindowBlocks", + "type" : "uint32" + } + ], + "indexed" : false, + "internalType" : "struct IDelegationManager.OperatorDetails", + "name" : "newOperatorDetails", + "type" : "tuple" + } + ], + "name" : "OperatorDetailsModified", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "string", + "name" : "metadataURI", + "type" : "string" + } + ], + "name" : "OperatorMetadataURIUpdated", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "components" : [ + { + "internalType" : "address", + "name" : "earningsReceiver", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegationApprover", + "type" : "address" + }, + { + "internalType" : "uint32", + "name" : "stakerOptOutWindowBlocks", + "type" : "uint32" + } + ], + "indexed" : false, + "internalType" : "struct IDelegationManager.OperatorDetails", + "name" : "operatorDetails", + "type" : "tuple" + } + ], + "name" : "OperatorRegistered", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "contract IStrategy", + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "uint256", + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "OperatorSharesDecreased", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "contract IStrategy", + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "uint256", + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "OperatorSharesIncreased", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "previousOwner", + "type" : "address" + }, + { + "indexed" : true, + "internalType" : "address", + "name" : "newOwner", + "type" : "address" + } + ], + "name" : "OwnershipTransferred", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "account", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "uint256", + "name" : "newPausedStatus", + "type" : "uint256" + } + ], + "name" : "Paused", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "internalType" : "contract IPauserRegistry", + "name" : "pauserRegistry", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "contract IPauserRegistry", + "name" : "newPauserRegistry", + "type" : "address" + } + ], + "name" : "PauserRegistrySet", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "StakerDelegated", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "StakerForceUndelegated", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "indexed" : true, + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "StakerUndelegated", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "internalType" : "contract IStrategy", + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "uint256", + "name" : "previousValue", + "type" : "uint256" + }, + { + "indexed" : false, + "internalType" : "uint256", + "name" : "newValue", + "type" : "uint256" + } + ], + "name" : "StrategyWithdrawalDelayBlocksSet", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "internalType" : "address", + "name" : "account", + "type" : "address" + }, + { + "indexed" : false, + "internalType" : "uint256", + "name" : "newPausedStatus", + "type" : "uint256" + } + ], + "name" : "Unpaused", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "internalType" : "bytes32", + "name" : "withdrawalRoot", + "type" : "bytes32" + } + ], + "name" : "WithdrawalCompleted", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "internalType" : "bytes32", + "name" : "oldWithdrawalRoot", + "type" : "bytes32" + }, + { + "indexed" : false, + "internalType" : "bytes32", + "name" : "newWithdrawalRoot", + "type" : "bytes32" + } + ], + "name" : "WithdrawalMigrated", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "internalType" : "bytes32", + "name" : "withdrawalRoot", + "type" : "bytes32" + }, + { + "components" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegatedTo", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "withdrawer", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "nonce", + "type" : "uint256" + }, + { + "internalType" : "uint32", + "name" : "startBlock", + "type" : "uint32" + }, + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "shares", + "type" : "uint256[]" + } + ], + "indexed" : false, + "internalType" : "struct IDelegationManager.Withdrawal", + "name" : "withdrawal", + "type" : "tuple" + } + ], + "name" : "WithdrawalQueued", + "type" : "event" + }, + { + "inputs" : [], + "name" : "DELEGATION_APPROVAL_TYPEHASH", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "DOMAIN_TYPEHASH", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "MAX_STAKER_OPT_OUT_WINDOW_BLOCKS", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "MAX_WITHDRAWAL_DELAY_BLOCKS", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "STAKER_DELEGATION_TYPEHASH", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "beaconChainETHStrategy", + "outputs" : [ + { + "internalType" : "contract IStrategy", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "expiry", + "type" : "uint256" + } + ], + "name" : "calculateCurrentStakerDelegationDigestHash", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "_delegationApprover", + "type" : "address" + }, + { + "internalType" : "bytes32", + "name" : "approverSalt", + "type" : "bytes32" + }, + { + "internalType" : "uint256", + "name" : "expiry", + "type" : "uint256" + } + ], + "name" : "calculateDelegationApprovalDigestHash", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "_stakerNonce", + "type" : "uint256" + }, + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "expiry", + "type" : "uint256" + } + ], + "name" : "calculateStakerDelegationDigestHash", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "components" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegatedTo", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "withdrawer", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "nonce", + "type" : "uint256" + }, + { + "internalType" : "uint32", + "name" : "startBlock", + "type" : "uint32" + }, + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "shares", + "type" : "uint256[]" + } + ], + "internalType" : "struct IDelegationManager.Withdrawal", + "name" : "withdrawal", + "type" : "tuple" + } + ], + "name" : "calculateWithdrawalRoot", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "pure", + "type" : "function" + }, + { + "inputs" : [ + { + "components" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegatedTo", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "withdrawer", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "nonce", + "type" : "uint256" + }, + { + "internalType" : "uint32", + "name" : "startBlock", + "type" : "uint32" + }, + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "shares", + "type" : "uint256[]" + } + ], + "internalType" : "struct IDelegationManager.Withdrawal", + "name" : "withdrawal", + "type" : "tuple" + }, + { + "internalType" : "contract IERC20[]", + "name" : "tokens", + "type" : "address[]" + }, + { + "internalType" : "uint256", + "name" : "middlewareTimesIndex", + "type" : "uint256" + }, + { + "internalType" : "bool", + "name" : "receiveAsTokens", + "type" : "bool" + } + ], + "name" : "completeQueuedWithdrawal", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "components" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegatedTo", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "withdrawer", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "nonce", + "type" : "uint256" + }, + { + "internalType" : "uint32", + "name" : "startBlock", + "type" : "uint32" + }, + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "shares", + "type" : "uint256[]" + } + ], + "internalType" : "struct IDelegationManager.Withdrawal[]", + "name" : "withdrawals", + "type" : "tuple[]" + }, + { + "internalType" : "contract IERC20[][]", + "name" : "tokens", + "type" : "address[][]" + }, + { + "internalType" : "uint256[]", + "name" : "middlewareTimesIndexes", + "type" : "uint256[]" + }, + { + "internalType" : "bool[]", + "name" : "receiveAsTokens", + "type" : "bool[]" + } + ], + "name" : "completeQueuedWithdrawals", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + } + ], + "name" : "cumulativeWithdrawalsQueued", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "contract IStrategy", + "name" : "strategy", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "decreaseDelegatedShares", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "components" : [ + { + "internalType" : "bytes", + "name" : "signature", + "type" : "bytes" + }, + { + "internalType" : "uint256", + "name" : "expiry", + "type" : "uint256" + } + ], + "internalType" : "struct ISignatureUtils.SignatureWithExpiry", + "name" : "approverSignatureAndExpiry", + "type" : "tuple" + }, + { + "internalType" : "bytes32", + "name" : "approverSalt", + "type" : "bytes32" + } + ], + "name" : "delegateTo", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "components" : [ + { + "internalType" : "bytes", + "name" : "signature", + "type" : "bytes" + }, + { + "internalType" : "uint256", + "name" : "expiry", + "type" : "uint256" + } + ], + "internalType" : "struct ISignatureUtils.SignatureWithExpiry", + "name" : "stakerSignatureAndExpiry", + "type" : "tuple" + }, + { + "components" : [ + { + "internalType" : "bytes", + "name" : "signature", + "type" : "bytes" + }, + { + "internalType" : "uint256", + "name" : "expiry", + "type" : "uint256" + } + ], + "internalType" : "struct ISignatureUtils.SignatureWithExpiry", + "name" : "approverSignatureAndExpiry", + "type" : "tuple" + }, + { + "internalType" : "bytes32", + "name" : "approverSalt", + "type" : "bytes32" + } + ], + "name" : "delegateToBySignature", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + } + ], + "name" : "delegatedTo", + "outputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "delegationApprover", + "outputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + }, + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "name" : "delegationApproverSaltIsSpent", + "outputs" : [ + { + "internalType" : "bool", + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "domainSeparator", + "outputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "earningsReceiver", + "outputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "eigenPodManager", + "outputs" : [ + { + "internalType" : "contract IEigenPodManager", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + } + ], + "name" : "getDelegatableShares", + "outputs" : [ + { + "internalType" : "contract IStrategy[]", + "name" : "", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "", + "type" : "uint256[]" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + }, + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + } + ], + "name" : "getOperatorShares", + "outputs" : [ + { + "internalType" : "uint256[]", + "name" : "", + "type" : "uint256[]" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + } + ], + "name" : "getWithdrawalDelay", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "internalType" : "contract IStrategy", + "name" : "strategy", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "increaseDelegatedShares", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "initialOwner", + "type" : "address" + }, + { + "internalType" : "contract IPauserRegistry", + "name" : "_pauserRegistry", + "type" : "address" + }, + { + "internalType" : "uint256", + "name" : "initialPausedStatus", + "type" : "uint256" + }, + { + "internalType" : "uint256", + "name" : "_minWithdrawalDelayBlocks", + "type" : "uint256" + }, + { + "internalType" : "contract IStrategy[]", + "name" : "_strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "_withdrawalDelayBlocks", + "type" : "uint256[]" + } + ], + "name" : "initialize", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + } + ], + "name" : "isDelegated", + "outputs" : [ + { + "internalType" : "bool", + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "isOperator", + "outputs" : [ + { + "internalType" : "bool", + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "components" : [ + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "shares", + "type" : "uint256[]" + }, + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + }, + { + "components" : [ + { + "internalType" : "address", + "name" : "withdrawer", + "type" : "address" + }, + { + "internalType" : "uint96", + "name" : "nonce", + "type" : "uint96" + } + ], + "internalType" : "struct IStrategyManager.DeprecatedStruct_WithdrawerAndNonce", + "name" : "withdrawerAndNonce", + "type" : "tuple" + }, + { + "internalType" : "uint32", + "name" : "withdrawalStartBlock", + "type" : "uint32" + }, + { + "internalType" : "address", + "name" : "delegatedAddress", + "type" : "address" + } + ], + "internalType" : "struct IStrategyManager.DeprecatedStruct_QueuedWithdrawal[]", + "name" : "withdrawalsToMigrate", + "type" : "tuple[]" + } + ], + "name" : "migrateQueuedWithdrawals", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [], + "name" : "minWithdrawalDelayBlocks", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "components" : [ + { + "internalType" : "address", + "name" : "earningsReceiver", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegationApprover", + "type" : "address" + }, + { + "internalType" : "uint32", + "name" : "stakerOptOutWindowBlocks", + "type" : "uint32" + } + ], + "internalType" : "struct IDelegationManager.OperatorDetails", + "name" : "newOperatorDetails", + "type" : "tuple" + } + ], + "name" : "modifyOperatorDetails", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "operatorDetails", + "outputs" : [ + { + "components" : [ + { + "internalType" : "address", + "name" : "earningsReceiver", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegationApprover", + "type" : "address" + }, + { + "internalType" : "uint32", + "name" : "stakerOptOutWindowBlocks", + "type" : "uint32" + } + ], + "internalType" : "struct IDelegationManager.OperatorDetails", + "name" : "", + "type" : "tuple" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + }, + { + "internalType" : "contract IStrategy", + "name" : "", + "type" : "address" + } + ], + "name" : "operatorShares", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "owner", + "outputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "uint256", + "name" : "newPausedStatus", + "type" : "uint256" + } + ], + "name" : "pause", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [], + "name" : "pauseAll", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "uint8", + "name" : "index", + "type" : "uint8" + } + ], + "name" : "paused", + "outputs" : [ + { + "internalType" : "bool", + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "paused", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "pauserRegistry", + "outputs" : [ + { + "internalType" : "contract IPauserRegistry", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "bytes32", + "name" : "", + "type" : "bytes32" + } + ], + "name" : "pendingWithdrawals", + "outputs" : [ + { + "internalType" : "bool", + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "components" : [ + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "shares", + "type" : "uint256[]" + }, + { + "internalType" : "address", + "name" : "withdrawer", + "type" : "address" + } + ], + "internalType" : "struct IDelegationManager.QueuedWithdrawalParams[]", + "name" : "queuedWithdrawalParams", + "type" : "tuple[]" + } + ], + "name" : "queueWithdrawals", + "outputs" : [ + { + "internalType" : "bytes32[]", + "name" : "", + "type" : "bytes32[]" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "components" : [ + { + "internalType" : "address", + "name" : "earningsReceiver", + "type" : "address" + }, + { + "internalType" : "address", + "name" : "delegationApprover", + "type" : "address" + }, + { + "internalType" : "uint32", + "name" : "stakerOptOutWindowBlocks", + "type" : "uint32" + } + ], + "internalType" : "struct IDelegationManager.OperatorDetails", + "name" : "registeringOperatorDetails", + "type" : "tuple" + }, + { + "internalType" : "string", + "name" : "metadataURI", + "type" : "string" + } + ], + "name" : "registerAsOperator", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [], + "name" : "renounceOwnership", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "uint256", + "name" : "newMinWithdrawalDelayBlocks", + "type" : "uint256" + } + ], + "name" : "setMinWithdrawalDelayBlocks", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "contract IPauserRegistry", + "name" : "newPauserRegistry", + "type" : "address" + } + ], + "name" : "setPauserRegistry", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "contract IStrategy[]", + "name" : "strategies", + "type" : "address[]" + }, + { + "internalType" : "uint256[]", + "name" : "withdrawalDelayBlocks", + "type" : "uint256[]" + } + ], + "name" : "setStrategyWithdrawalDelayBlocks", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [], + "name" : "slasher", + "outputs" : [ + { + "internalType" : "contract ISlasher", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "", + "type" : "address" + } + ], + "name" : "stakerNonce", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "operator", + "type" : "address" + } + ], + "name" : "stakerOptOutWindowBlocks", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "strategyManager", + "outputs" : [ + { + "internalType" : "contract IStrategyManager", + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "contract IStrategy", + "name" : "", + "type" : "address" + } + ], + "name" : "strategyWithdrawalDelayBlocks", + "outputs" : [ + { + "internalType" : "uint256", + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "newOwner", + "type" : "address" + } + ], + "name" : "transferOwnership", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "address", + "name" : "staker", + "type" : "address" + } + ], + "name" : "undelegate", + "outputs" : [ + { + "internalType" : "bytes32[]", + "name" : "withdrawalRoots", + "type" : "bytes32[]" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "uint256", + "name" : "newPausedStatus", + "type" : "uint256" + } + ], + "name" : "unpause", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "internalType" : "string", + "name" : "metadataURI", + "type" : "string" + } + ], + "name" : "updateOperatorMetadataURI", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + } +] diff --git a/tests/ragger/abis/rSWELL.abi.json b/tests/ragger/abis/rSWELL.abi.json new file mode 100644 index 0000000000..2747ae2753 --- /dev/null +++ b/tests/ragger/abis/rSWELL.abi.json @@ -0,0 +1,1798 @@ +[ + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "sender", + "type" : "address" + }, + { + "indexed" : true, + "name" : "owner", + "type" : "address" + }, + { + "indexed" : false, + "name" : "assets", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "Deposit", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "sender", + "type" : "address" + }, + { + "indexed" : true, + "name" : "receiver", + "type" : "address" + }, + { + "indexed" : true, + "name" : "owner", + "type" : "address" + }, + { + "indexed" : false, + "name" : "assets", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "Withdraw", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "sender", + "type" : "address" + }, + { + "indexed" : true, + "name" : "receiver", + "type" : "address" + }, + { + "indexed" : false, + "name" : "value", + "type" : "uint256" + } + ], + "name" : "Transfer", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "owner", + "type" : "address" + }, + { + "indexed" : true, + "name" : "spender", + "type" : "address" + }, + { + "indexed" : false, + "name" : "value", + "type" : "uint256" + } + ], + "name" : "Approval", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : true, + "name" : "change_type", + "type" : "uint256" + } + ], + "name" : "StrategyChanged", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : false, + "name" : "gain", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "loss", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "current_debt", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "protocol_fees", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "total_fees", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "total_refunds", + "type" : "uint256" + } + ], + "name" : "StrategyReported", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : false, + "name" : "current_debt", + "type" : "uint256" + }, + { + "indexed" : false, + "name" : "new_debt", + "type" : "uint256" + } + ], + "name" : "DebtUpdated", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "account", + "type" : "address" + }, + { + "indexed" : true, + "name" : "role", + "type" : "uint256" + } + ], + "name" : "RoleSet", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "role_manager", + "type" : "address" + } + ], + "name" : "UpdateRoleManager", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "accountant", + "type" : "address" + } + ], + "name" : "UpdateAccountant", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "deposit_limit_module", + "type" : "address" + } + ], + "name" : "UpdateDepositLimitModule", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "withdraw_limit_module", + "type" : "address" + } + ], + "name" : "UpdateWithdrawLimitModule", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "name" : "new_default_queue", + "type" : "address[]" + } + ], + "name" : "UpdateDefaultQueue", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "name" : "use_default_queue", + "type" : "bool" + } + ], + "name" : "UpdateUseDefaultQueue", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "sender", + "type" : "address" + }, + { + "indexed" : true, + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : false, + "name" : "new_debt", + "type" : "uint256" + } + ], + "name" : "UpdatedMaxDebtForStrategy", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "name" : "deposit_limit", + "type" : "uint256" + } + ], + "name" : "UpdateDepositLimit", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "name" : "minimum_total_idle", + "type" : "uint256" + } + ], + "name" : "UpdateMinimumTotalIdle", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : false, + "name" : "profit_max_unlock_time", + "type" : "uint256" + } + ], + "name" : "UpdateProfitMaxUnlockTime", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [ + { + "indexed" : true, + "name" : "strategy", + "type" : "address" + }, + { + "indexed" : false, + "name" : "amount", + "type" : "uint256" + } + ], + "name" : "DebtPurchased", + "type" : "event" + }, + { + "anonymous" : false, + "inputs" : [], + "name" : "Shutdown", + "type" : "event" + }, + { + "inputs" : [], + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "constructor" + }, + { + "inputs" : [ + { + "name" : "asset", + "type" : "address" + }, + { + "name" : "name", + "type" : "string" + }, + { + "name" : "symbol", + "type" : "string" + }, + { + "name" : "role_manager", + "type" : "address" + }, + { + "name" : "profit_max_unlock_time", + "type" : "uint256" + } + ], + "name" : "initialize", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "new_accountant", + "type" : "address" + } + ], + "name" : "set_accountant", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "new_default_queue", + "type" : "address[]" + } + ], + "name" : "set_default_queue", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "use_default_queue", + "type" : "bool" + } + ], + "name" : "set_use_default_queue", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "deposit_limit", + "type" : "uint256" + } + ], + "name" : "set_deposit_limit", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "deposit_limit", + "type" : "uint256" + }, + { + "name" : "override", + "type" : "bool" + } + ], + "name" : "set_deposit_limit", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "deposit_limit_module", + "type" : "address" + } + ], + "name" : "set_deposit_limit_module", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "deposit_limit_module", + "type" : "address" + }, + { + "name" : "override", + "type" : "bool" + } + ], + "name" : "set_deposit_limit_module", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "withdraw_limit_module", + "type" : "address" + } + ], + "name" : "set_withdraw_limit_module", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "minimum_total_idle", + "type" : "uint256" + } + ], + "name" : "set_minimum_total_idle", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "new_profit_max_unlock_time", + "type" : "uint256" + } + ], + "name" : "setProfitMaxUnlockTime", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "account", + "type" : "address" + }, + { + "name" : "role", + "type" : "uint256" + } + ], + "name" : "set_role", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "account", + "type" : "address" + }, + { + "name" : "role", + "type" : "uint256" + } + ], + "name" : "add_role", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "account", + "type" : "address" + }, + { + "name" : "role", + "type" : "uint256" + } + ], + "name" : "remove_role", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "role_manager", + "type" : "address" + } + ], + "name" : "transfer_role_manager", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [], + "name" : "accept_role_manager", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [], + "name" : "isShutdown", + "outputs" : [ + { + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "unlockedShares", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "pricePerShare", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "get_default_queue", + "outputs" : [ + { + "name" : "", + "type" : "address[]" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + } + ], + "name" : "process_report", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + }, + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + }, + { + "name" : "amount", + "type" : "uint256" + } + ], + "name" : "buy_debt", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "new_strategy", + "type" : "address" + } + ], + "name" : "add_strategy", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "new_strategy", + "type" : "address" + }, + { + "name" : "add_to_queue", + "type" : "bool" + } + ], + "name" : "add_strategy", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + } + ], + "name" : "revoke_strategy", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + } + ], + "name" : "force_revoke_strategy", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + }, + { + "name" : "new_max_debt", + "type" : "uint256" + } + ], + "name" : "update_max_debt_for_strategy", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + }, + { + "name" : "target_debt", + "type" : "uint256" + } + ], + "name" : "update_debt", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + }, + { + "name" : "target_debt", + "type" : "uint256" + }, + { + "name" : "max_loss", + "type" : "uint256" + } + ], + "name" : "update_debt", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [], + "name" : "shutdown_vault", + "outputs" : [], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "assets", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + } + ], + "name" : "deposit", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "shares", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + } + ], + "name" : "mint", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "assets", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "owner", + "type" : "address" + } + ], + "name" : "withdraw", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "assets", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + } + ], + "name" : "withdraw", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "assets", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + }, + { + "name" : "strategies", + "type" : "address[]" + } + ], + "name" : "withdraw", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "shares", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "owner", + "type" : "address" + } + ], + "name" : "redeem", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "shares", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + } + ], + "name" : "redeem", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "shares", + "type" : "uint256" + }, + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + }, + { + "name" : "strategies", + "type" : "address[]" + } + ], + "name" : "redeem", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "spender", + "type" : "address" + }, + { + "name" : "amount", + "type" : "uint256" + } + ], + "name" : "approve", + "outputs" : [ + { + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "amount", + "type" : "uint256" + } + ], + "name" : "transfer", + "outputs" : [ + { + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "sender", + "type" : "address" + }, + { + "name" : "receiver", + "type" : "address" + }, + { + "name" : "amount", + "type" : "uint256" + } + ], + "name" : "transferFrom", + "outputs" : [ + { + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "spender", + "type" : "address" + }, + { + "name" : "amount", + "type" : "uint256" + }, + { + "name" : "deadline", + "type" : "uint256" + }, + { + "name" : "v", + "type" : "uint8" + }, + { + "name" : "r", + "type" : "bytes32" + }, + { + "name" : "s", + "type" : "bytes32" + } + ], + "name" : "permit", + "outputs" : [ + { + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "nonpayable", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "addr", + "type" : "address" + } + ], + "name" : "balanceOf", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "totalSupply", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "totalAssets", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "totalIdle", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "totalDebt", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "assets", + "type" : "uint256" + } + ], + "name" : "convertToShares", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "assets", + "type" : "uint256" + } + ], + "name" : "previewDeposit", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "previewMint", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "convertToAssets", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "receiver", + "type" : "address" + } + ], + "name" : "maxDeposit", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "receiver", + "type" : "address" + } + ], + "name" : "maxMint", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "owner", + "type" : "address" + } + ], + "name" : "maxWithdraw", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + } + ], + "name" : "maxWithdraw", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + }, + { + "name" : "strategies", + "type" : "address[]" + } + ], + "name" : "maxWithdraw", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "owner", + "type" : "address" + } + ], + "name" : "maxRedeem", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + } + ], + "name" : "maxRedeem", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "owner", + "type" : "address" + }, + { + "name" : "max_loss", + "type" : "uint256" + }, + { + "name" : "strategies", + "type" : "address[]" + } + ], + "name" : "maxRedeem", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "assets", + "type" : "uint256" + } + ], + "name" : "previewWithdraw", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "shares", + "type" : "uint256" + } + ], + "name" : "previewRedeem", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "FACTORY", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "apiVersion", + "outputs" : [ + { + "name" : "", + "type" : "string" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "strategy", + "type" : "address" + }, + { + "name" : "assets_needed", + "type" : "uint256" + } + ], + "name" : "assess_share_of_unrealised_losses", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "profitMaxUnlockTime", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "fullProfitUnlockDate", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "profitUnlockingRate", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "lastProfitUpdate", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "DOMAIN_SEPARATOR", + "outputs" : [ + { + "name" : "", + "type" : "bytes32" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "asset", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "decimals", + "outputs" : [ + { + "name" : "", + "type" : "uint8" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "arg0", + "type" : "address" + } + ], + "name" : "strategies", + "outputs" : [ + { + "components" : [ + { + "name" : "activation", + "type" : "uint256" + }, + { + "name" : "last_report", + "type" : "uint256" + }, + { + "name" : "current_debt", + "type" : "uint256" + }, + { + "name" : "max_debt", + "type" : "uint256" + } + ], + "name" : "", + "type" : "tuple" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "arg0", + "type" : "uint256" + } + ], + "name" : "default_queue", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "use_default_queue", + "outputs" : [ + { + "name" : "", + "type" : "bool" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "arg0", + "type" : "address" + }, + { + "name" : "arg1", + "type" : "address" + } + ], + "name" : "allowance", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "minimum_total_idle", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "deposit_limit", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "accountant", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "deposit_limit_module", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "withdraw_limit_module", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "arg0", + "type" : "address" + } + ], + "name" : "roles", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "role_manager", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "future_role_manager", + "outputs" : [ + { + "name" : "", + "type" : "address" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "name", + "outputs" : [ + { + "name" : "", + "type" : "string" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [], + "name" : "symbol", + "outputs" : [ + { + "name" : "", + "type" : "string" + } + ], + "stateMutability" : "view", + "type" : "function" + }, + { + "inputs" : [ + { + "name" : "arg0", + "type" : "address" + } + ], + "name" : "nonces", + "outputs" : [ + { + "name" : "", + "type" : "uint256" + } + ], + "stateMutability" : "view", + "type" : "function" + } +] diff --git a/tests/ragger/conftest.py b/tests/ragger/conftest.py index 2f1eac38c0..7f2d57ecb9 100644 --- a/tests/ragger/conftest.py +++ b/tests/ragger/conftest.py @@ -1,8 +1,5 @@ -import sys from pathlib import Path -from os import path import warnings -import glob import re import pytest @@ -18,39 +15,20 @@ # ragger.configuration.OPTIONAL_CONFIGURATION # Please refer to ragger/conftest/configuration.py for their descriptions and accepted values +configuration.OPTIONAL.ALLOWED_SETUPS = ["default", "lib_mode"] -def pytest_addoption(parser): - parser.addoption("--with_lib_mode", action="store_true", help="Run the test with Library Mode") - -pattern = f"{Path(__file__).parent}/test_*.py" -testFiles = [path.basename(x) for x in glob.glob(pattern)] -collect_ignore = [] -if "--with_lib_mode" in sys.argv: - - # ============================================================================== - # /!\ Tests are started in Library mode: unselect (ignore) unrelated modules /!\ - # ============================================================================== - - warnings.warn("Main app is started in library mode") - - configuration.OPTIONAL.MAIN_APP_DIR = "tests/ragger/.test_dependencies/" - - collect_ignore += [f for f in testFiles if "test_clone" not in f] - -else: - - # =========================================================================== - # /!\ Standards tests without Library mode: unselect (ignore) clone tests /!\ - # =========================================================================== - - collect_ignore += [f for f in testFiles if "test_clone" in f] +def pytest_configure(config): + current_setup = config.getoption("--setup") + if current_setup == "lib_mode": + warnings.warn("Main app is started in library mode") + configuration.OPTIONAL.MAIN_APP_DIR = "tests/ragger/.test_dependencies/" @pytest.fixture(name="app_version") def app_version_fixture(request) -> tuple[int, int, int]: - with open(Path(__file__).parent.parent.parent / "Makefile") as f: - parsed = dict() + with open(Path(__file__).parent.parent.parent / "Makefile", encoding="utf-8") as f: + parsed = {} for m in re.findall(r"^APPVERSION_(\w)\s*=\s*(\d*)$", f.read(), re.MULTILINE): parsed[m[0]] = int(m[1]) return (parsed["M"], parsed["N"], parsed["P"]) diff --git a/tests/ragger/setup.cfg b/tests/ragger/setup.cfg index 4a673e2c3a..a2fd6373ff 100644 --- a/tests/ragger/setup.cfg +++ b/tests/ragger/setup.cfg @@ -7,6 +7,7 @@ disable = C0114, # missing-module-docstring C0116, # missing-function-docstring C0103, # invalid-name R0801, # duplicate-code + R0902, # too-many-instance-attributes R0903, # too-few-public-methods R0904, # too-many-public-methods R0911, # too-many-statements @@ -14,6 +15,7 @@ disable = C0114, # missing-module-docstring R0913, # too-many-arguments R0914, # too-many-locals R0915, # too-many-statements + R0917, # too-many-positional-arguments W0603, # global-statement E0401 # import-error extension-pkg-whitelist=hid diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00000.png deleted file mode 100644 index 3b0deb8ab8..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00004.png b/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00004.png deleted file mode 100644 index e3a8717000..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00000.png b/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00000.png deleted file mode 100644 index 982c8deccc..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00004.png b/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00004.png deleted file mode 100644 index 281622f912..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00000.png b/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00000.png deleted file mode 100644 index f680a467d0..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00004.png b/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00004.png deleted file mode 100644 index ae2e73aa6d..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00000.png deleted file mode 100644 index 2d8a17b371..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00004.png deleted file mode 100644 index e77ed86900..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00000.png deleted file mode 100644 index 2d8a17b371..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00004.png deleted file mode 100644 index e77ed86900..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00000.png deleted file mode 100644 index fd048b2cf5..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00004.png deleted file mode 100644 index 6e6068cc45..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00000.png deleted file mode 100644 index 4779e9052d..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00004.png deleted file mode 100644 index 048bbf4b41..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00000.png deleted file mode 100644 index 0c5fa6f327..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00003.png deleted file mode 100644 index bc9c251055..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00000.png deleted file mode 100644 index 3e45373cfd..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00003.png deleted file mode 100644 index ddb2ddc5cc..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00000.png deleted file mode 100644 index f1247b5cef..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00003.png deleted file mode 100644 index 3f41be8096..0000000000 Binary files a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_1/00000.png b/tests/ragger/snapshots/flex/erc721_approve_1/00000.png deleted file mode 100644 index 0c5fa6f327..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_approve_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_1/00003.png b/tests/ragger/snapshots/flex/erc721_approve_1/00003.png deleted file mode 100644 index bc9c251055..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_approve_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_137/00000.png b/tests/ragger/snapshots/flex/erc721_approve_137/00000.png deleted file mode 100644 index 8ac194e70a..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_approve_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_137/00004.png b/tests/ragger/snapshots/flex/erc721_approve_137/00004.png deleted file mode 100644 index 4866ce73bf..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_approve_137/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_5/00000.png b/tests/ragger/snapshots/flex/erc721_approve_5/00000.png deleted file mode 100644 index f5ff49d3f0..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_approve_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_5/00004.png b/tests/ragger/snapshots/flex/erc721_approve_5/00004.png deleted file mode 100644 index 66e0703ccc..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_approve_5/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00000.png deleted file mode 100644 index dd797e4770..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00003.png deleted file mode 100644 index 1e3909a7c9..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00000.png deleted file mode 100644 index dd797e4770..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00003.png deleted file mode 100644 index 1e3909a7c9..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00000.png deleted file mode 100644 index fd048b2cf5..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00004.png deleted file mode 100644 index 6e6068cc45..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00000.png deleted file mode 100644 index 4779e9052d..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00004.png deleted file mode 100644 index 048bbf4b41..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00000.png deleted file mode 100644 index 0c5fa6f327..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00003.png deleted file mode 100644 index bc9c251055..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00000.png deleted file mode 100644 index 3e45373cfd..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00003.png deleted file mode 100644 index ddb2ddc5cc..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00000.png deleted file mode 100644 index f1247b5cef..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00003.png deleted file mode 100644 index 3f41be8096..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00000.png b/tests/ragger/snapshots/flex/erc721_transferFrom_1/00000.png deleted file mode 100644 index dd797e4770..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00003.png b/tests/ragger/snapshots/flex/erc721_transferFrom_1/00003.png deleted file mode 100644 index 1e3909a7c9..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00000.png b/tests/ragger/snapshots/flex/erc721_transferFrom_137/00000.png deleted file mode 100644 index fd048b2cf5..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00004.png b/tests/ragger/snapshots/flex/erc721_transferFrom_137/00004.png deleted file mode 100644 index 6e6068cc45..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00000.png b/tests/ragger/snapshots/flex/erc721_transferFrom_5/00000.png deleted file mode 100644 index 4779e9052d..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00004.png b/tests/ragger/snapshots/flex/erc721_transferFrom_5/00004.png deleted file mode 100644 index 048bbf4b41..0000000000 Binary files a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_1inch/00000.png b/tests/ragger/snapshots/flex/test_1inch/00000.png deleted file mode 100644 index bb8112a269..0000000000 Binary files a/tests/ragger/snapshots/flex/test_1inch/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_1inch/00001.png b/tests/ragger/snapshots/flex/test_1inch/00001.png deleted file mode 100644 index df31358114..0000000000 Binary files a/tests/ragger/snapshots/flex/test_1inch/00001.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_1inch/00002.png b/tests/ragger/snapshots/flex/test_1inch/00002.png deleted file mode 100644 index 68b268c9f8..0000000000 Binary files a/tests/ragger/snapshots/flex/test_1inch/00002.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign/00000.png b/tests/ragger/snapshots/flex/test_blind_sign/00000.png index 039eff0472..30c604f3dd 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign/00000.png and b/tests/ragger/snapshots/flex/test_blind_sign/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign/00001.png b/tests/ragger/snapshots/flex/test_blind_sign/00001.png index a36989ec66..e903fe8357 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign/00001.png and b/tests/ragger/snapshots/flex/test_blind_sign/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign/00002.png b/tests/ragger/snapshots/flex/test_blind_sign/00002.png index e903fe8357..fdf1457d2a 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign/00002.png and b/tests/ragger/snapshots/flex/test_blind_sign/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign/00003.png b/tests/ragger/snapshots/flex/test_blind_sign/00003.png index fdf1457d2a..aeb3c483dd 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign/00003.png and b/tests/ragger/snapshots/flex/test_blind_sign/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign/00004.png b/tests/ragger/snapshots/flex/test_blind_sign/00004.png index aeb3c483dd..be51a9d559 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign/00004.png and b/tests/ragger/snapshots/flex/test_blind_sign/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign/00005.png b/tests/ragger/snapshots/flex/test_blind_sign/00005.png index be51a9d559..dabe7afea3 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign/00005.png and b/tests/ragger/snapshots/flex/test_blind_sign/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign/warning/00000.png b/tests/ragger/snapshots/flex/test_blind_sign/warning/00000.png new file mode 100644 index 0000000000..d17942d01e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_blind_sign/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00000.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00000.png index 039eff0472..30c604f3dd 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00000.png and b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00001.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00001.png index a36989ec66..3119953c6b 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00001.png and b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00002.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00002.png index 3119953c6b..cb8ab9f822 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00002.png and b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00003.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00003.png index cb8ab9f822..aeb3c483dd 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00003.png and b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00004.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00004.png index aeb3c483dd..be51a9d559 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00004.png and b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00005.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00005.png index be51a9d559..dabe7afea3 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00005.png and b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonzero/warning/00000.png b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/warning/00000.png new file mode 100644 index 0000000000..d17942d01e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_blind_sign_nonzero/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00000.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00000.png index 039eff0472..30c604f3dd 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00000.png and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00001.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00001.png index a36989ec66..e903fe8357 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00001.png and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00002.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00002.png index e903fe8357..fdf1457d2a 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00002.png and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00003.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00003.png index fdf1457d2a..aeb3c483dd 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00003.png and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00004.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00004.png index aeb3c483dd..6a11e11873 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00004.png and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00005.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00005.png index 6a11e11873..6bbdf2ff32 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00005.png and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00006.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00006.png index 6bbdf2ff32..dabe7afea3 100644 Binary files a/tests/ragger/snapshots/flex/test_blind_sign_rejected/00006.png and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_rejected/warning/00000.png b/tests/ragger/snapshots/flex/test_blind_sign_rejected/warning/00000.png new file mode 100644 index 0000000000..d17942d01e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_blind_sign_rejected/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_1inch/00000.png b/tests/ragger/snapshots/flex/test_gcs_1inch/00000.png new file mode 100644 index 0000000000..f2863cfa91 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_1inch/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_1inch/00001.png b/tests/ragger/snapshots/flex/test_gcs_1inch/00001.png new file mode 100644 index 0000000000..cbfce4262e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_1inch/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_1inch/00002.png b/tests/ragger/snapshots/flex/test_gcs_1inch/00002.png new file mode 100644 index 0000000000..f6c8378eae Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_1inch/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_1inch/00003.png b/tests/ragger/snapshots/flex/test_gcs_1inch/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/test_1inch/00003.png rename to tests/ragger/snapshots/flex/test_gcs_1inch/00003.png diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/flex/test_gcs_1inch/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/flex/test_gcs_1inch/00004.png diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/flex/test_gcs_1inch/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/flex/test_gcs_1inch/00005.png diff --git a/tests/ragger/snapshots/flex/test_gcs_4226/00000.png b/tests/ragger/snapshots/flex/test_gcs_4226/00000.png new file mode 100644 index 0000000000..d28fba84a2 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_4226/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_4226/00001.png b/tests/ragger/snapshots/flex/test_gcs_4226/00001.png new file mode 100644 index 0000000000..61d96001ca Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_4226/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_4226/00002.png b/tests/ragger/snapshots/flex/test_gcs_4226/00002.png new file mode 100644 index 0000000000..d9c6577167 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_4226/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_4226/00003.png b/tests/ragger/snapshots/flex/test_gcs_4226/00003.png new file mode 100644 index 0000000000..247b53677b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_4226/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/flex/test_gcs_4226/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/flex/test_gcs_4226/00004.png diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/flex/test_gcs_4226/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/flex/test_gcs_4226/00005.png diff --git a/tests/ragger/snapshots/flex/test_gcs_nft/00000.png b/tests/ragger/snapshots/flex/test_gcs_nft/00000.png new file mode 100644 index 0000000000..7456ebcdd8 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nft/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nft/00001.png b/tests/ragger/snapshots/flex/test_gcs_nft/00001.png new file mode 100644 index 0000000000..74e6ce7e38 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nft/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nft/00002.png b/tests/ragger/snapshots/flex/test_gcs_nft/00002.png new file mode 100644 index 0000000000..ab0eabed0f Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nft/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nft/00003.png b/tests/ragger/snapshots/flex/test_gcs_nft/00003.png new file mode 100644 index 0000000000..959baf0391 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nft/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nft/00004.png b/tests/ragger/snapshots/flex/test_gcs_nft/00004.png new file mode 100644 index 0000000000..6a6f264ecf Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nft/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_nft/00005.png b/tests/ragger/snapshots/flex/test_gcs_nft/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/test_nft/00005.png rename to tests/ragger/snapshots/flex/test_gcs_nft/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft/00006.png b/tests/ragger/snapshots/flex/test_gcs_nft/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/test_nft/00006.png rename to tests/ragger/snapshots/flex/test_gcs_nft/00006.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00007.png b/tests/ragger/snapshots/flex/test_gcs_nft/00007.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00007.png rename to tests/ragger/snapshots/flex/test_gcs_nft/00007.png diff --git a/tests/ragger/snapshots/flex/test_gcs_poap/00000.png b/tests/ragger/snapshots/flex/test_gcs_poap/00000.png new file mode 100644 index 0000000000..99e91bcc65 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_poap/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_poap/00001.png b/tests/ragger/snapshots/flex/test_gcs_poap/00001.png new file mode 100644 index 0000000000..60ec3f04d5 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_poap/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_poap/00002.png b/tests/ragger/snapshots/flex/test_gcs_poap/00002.png new file mode 100644 index 0000000000..f15e93debd Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_poap/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_poap/00003.png b/tests/ragger/snapshots/flex/test_gcs_poap/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/test_poap/00003.png rename to tests/ragger/snapshots/flex/test_gcs_poap/00003.png diff --git a/tests/ragger/snapshots/flex/test_poap/00004.png b/tests/ragger/snapshots/flex/test_gcs_poap/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/test_poap/00004.png rename to tests/ragger/snapshots/flex/test_gcs_poap/00004.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00005.png b/tests/ragger/snapshots/flex/test_gcs_poap/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00005.png rename to tests/ragger/snapshots/flex/test_gcs_poap/00005.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00006.png b/tests/ragger/snapshots/flex/test_gcs_poap/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00006.png rename to tests/ragger/snapshots/flex/test_gcs_poap/00006.png diff --git a/tests/ragger/snapshots/flex/test_gcs_proxy/00000.png b/tests/ragger/snapshots/flex/test_gcs_proxy/00000.png new file mode 100644 index 0000000000..459742f1a0 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_proxy/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_proxy/00001.png b/tests/ragger/snapshots/flex/test_gcs_proxy/00001.png new file mode 100644 index 0000000000..3e56273788 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_proxy/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_proxy/00002.png b/tests/ragger/snapshots/flex/test_gcs_proxy/00002.png new file mode 100644 index 0000000000..605c6b0bde Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_proxy/00002.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00005.png b/tests/ragger/snapshots/flex/test_gcs_proxy/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00005.png rename to tests/ragger/snapshots/flex/test_gcs_proxy/00003.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00006.png b/tests/ragger/snapshots/flex/test_gcs_proxy/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00006.png rename to tests/ragger/snapshots/flex/test_gcs_proxy/00004.png diff --git a/tests/ragger/snapshots/flex/get_pk_1/00000.png b/tests/ragger/snapshots/flex/test_get_pk_1/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_1/00000.png rename to tests/ragger/snapshots/flex/test_get_pk_1/00000.png diff --git a/tests/ragger/snapshots/flex/get_pk_1/00001.png b/tests/ragger/snapshots/flex/test_get_pk_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_1/00001.png rename to tests/ragger/snapshots/flex/test_get_pk_1/00001.png diff --git a/tests/ragger/snapshots/flex/get_pk_1/00002.png b/tests/ragger/snapshots/flex/test_get_pk_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_1/00002.png rename to tests/ragger/snapshots/flex/test_get_pk_1/00002.png diff --git a/tests/ragger/snapshots/flex/get_pk_1/00003.png b/tests/ragger/snapshots/flex/test_get_pk_1/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_1/00003.png rename to tests/ragger/snapshots/flex/test_get_pk_1/00003.png diff --git a/tests/ragger/snapshots/flex/get_pk_137/00000.png b/tests/ragger/snapshots/flex/test_get_pk_137/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_137/00000.png rename to tests/ragger/snapshots/flex/test_get_pk_137/00000.png diff --git a/tests/ragger/snapshots/flex/get_pk_137/00001.png b/tests/ragger/snapshots/flex/test_get_pk_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_137/00001.png rename to tests/ragger/snapshots/flex/test_get_pk_137/00001.png diff --git a/tests/ragger/snapshots/flex/get_pk_137/00002.png b/tests/ragger/snapshots/flex/test_get_pk_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_137/00002.png rename to tests/ragger/snapshots/flex/test_get_pk_137/00002.png diff --git a/tests/ragger/snapshots/flex/get_pk_137/00003.png b/tests/ragger/snapshots/flex/test_get_pk_137/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_137/00003.png rename to tests/ragger/snapshots/flex/test_get_pk_137/00003.png diff --git a/tests/ragger/snapshots/flex/get_pk_2/00000.png b/tests/ragger/snapshots/flex/test_get_pk_2/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_2/00000.png rename to tests/ragger/snapshots/flex/test_get_pk_2/00000.png diff --git a/tests/ragger/snapshots/flex/get_pk_2/00001.png b/tests/ragger/snapshots/flex/test_get_pk_2/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_2/00001.png rename to tests/ragger/snapshots/flex/test_get_pk_2/00001.png diff --git a/tests/ragger/snapshots/flex/get_pk_2/00002.png b/tests/ragger/snapshots/flex/test_get_pk_2/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_2/00002.png rename to tests/ragger/snapshots/flex/test_get_pk_2/00002.png diff --git a/tests/ragger/snapshots/flex/get_pk_2/00003.png b/tests/ragger/snapshots/flex/test_get_pk_2/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_2/00003.png rename to tests/ragger/snapshots/flex/test_get_pk_2/00003.png diff --git a/tests/ragger/snapshots/flex/get_pk_5/00000.png b/tests/ragger/snapshots/flex/test_get_pk_5/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_5/00000.png rename to tests/ragger/snapshots/flex/test_get_pk_5/00000.png diff --git a/tests/ragger/snapshots/flex/get_pk_5/00001.png b/tests/ragger/snapshots/flex/test_get_pk_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_5/00001.png rename to tests/ragger/snapshots/flex/test_get_pk_5/00001.png diff --git a/tests/ragger/snapshots/flex/get_pk_5/00002.png b/tests/ragger/snapshots/flex/test_get_pk_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_5/00002.png rename to tests/ragger/snapshots/flex/test_get_pk_5/00002.png diff --git a/tests/ragger/snapshots/flex/get_pk_5/00003.png b/tests/ragger/snapshots/flex/test_get_pk_5/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_5/00003.png rename to tests/ragger/snapshots/flex/test_get_pk_5/00003.png diff --git a/tests/ragger/snapshots/flex/get_pk_None/00000.png b/tests/ragger/snapshots/flex/test_get_pk_None/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_None/00000.png rename to tests/ragger/snapshots/flex/test_get_pk_None/00000.png diff --git a/tests/ragger/snapshots/flex/get_pk_None/00001.png b/tests/ragger/snapshots/flex/test_get_pk_None/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_None/00001.png rename to tests/ragger/snapshots/flex/test_get_pk_None/00001.png diff --git a/tests/ragger/snapshots/flex/get_pk_None/00002.png b/tests/ragger/snapshots/flex/test_get_pk_None/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_None/00002.png rename to tests/ragger/snapshots/flex/test_get_pk_None/00002.png diff --git a/tests/ragger/snapshots/flex/get_pk_None/00003.png b/tests/ragger/snapshots/flex/test_get_pk_None/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_None/00003.png rename to tests/ragger/snapshots/flex/test_get_pk_None/00003.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_60/00000.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_60/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_60/00000.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_60/00000.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_60/00001.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_60/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_60/00001.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_60/00001.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_60/00002.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_60/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_60/00002.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_60/00002.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_60/00003.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_60/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_60/00003.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_60/00003.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_700/00000.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_700/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_700/00000.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_700/00000.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_700/00001.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_700/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_700/00001.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_700/00001.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_700/00002.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_700/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_700/00002.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_700/00002.png diff --git a/tests/ragger/snapshots/flex/get_pk_rejected_700/00003.png b/tests/ragger/snapshots/flex/test_get_pk_rejected_700/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/get_pk_rejected_700/00003.png rename to tests/ragger/snapshots/flex/test_get_pk_rejected_700/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft/00000.png b/tests/ragger/snapshots/flex/test_nft/00000.png deleted file mode 100644 index dcae9dcaf4..0000000000 Binary files a/tests/ragger/snapshots/flex/test_nft/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_nft/00001.png b/tests/ragger/snapshots/flex/test_nft/00001.png deleted file mode 100644 index a734438eeb..0000000000 Binary files a/tests/ragger/snapshots/flex/test_nft/00001.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_nft/00002.png b/tests/ragger/snapshots/flex/test_nft/00002.png deleted file mode 100644 index d0da7df405..0000000000 Binary files a/tests/ragger/snapshots/flex/test_nft/00002.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_nft/00003.png b/tests/ragger/snapshots/flex/test_nft/00003.png deleted file mode 100644 index f1eacdc137..0000000000 Binary files a/tests/ragger/snapshots/flex/test_nft/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_nft/00004.png b/tests/ragger/snapshots/flex/test_nft/00004.png deleted file mode 100644 index 3ade03afd0..0000000000 Binary files a/tests/ragger/snapshots/flex/test_nft/00004.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..6ecc20878b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00004.png new file mode 100644 index 0000000000..07f774dc15 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft/00007.png b/tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/flex/test_nft/00007.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_reject_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00000.png new file mode 100644 index 0000000000..bd4f756abe Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_1/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00004.png new file mode 100644 index 0000000000..9c2590be9c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00006.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00000.png new file mode 100644 index 0000000000..bccc068a33 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_137/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00004.png new file mode 100644 index 0000000000..1c674e4220 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00000.png new file mode 100644 index 0000000000..2e9f44984b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeBatchTransferFrom_5/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00004.png new file mode 100644 index 0000000000..caa9d2adc9 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeBatchTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..6ecc20878b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_1/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00004.png new file mode 100644 index 0000000000..07f774dc15 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00000.png new file mode 100644 index 0000000000..a692538cb6 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_137/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00004.png new file mode 100644 index 0000000000..3db14db31b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_137/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_137/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_137/00006.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_137/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00000.png new file mode 100644 index 0000000000..f7114abc90 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_safeTransferFrom_5/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00004.png new file mode 100644 index 0000000000..da1a95050f Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_5/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_5/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_5/00006.png b/tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_5/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_safeTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00000.png new file mode 100644 index 0000000000..3868573124 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00003.png new file mode 100644 index 0000000000..6ebb7d15d1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00000.png new file mode 100644 index 0000000000..058addd37e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00003.png new file mode 100644 index 0000000000..73e38ddc76 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_1/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_1/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_1/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_1/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00000.png new file mode 100644 index 0000000000..8d29aefd95 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc1155_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00003.png new file mode 100644 index 0000000000..1a28caf59e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc1155_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00000.png new file mode 100644 index 0000000000..3868573124 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_1/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_1/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_1/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_1/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00003.png new file mode 100644 index 0000000000..6ebb7d15d1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00004.png diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_1/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00000.png new file mode 100644 index 0000000000..2baa18d1bb Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_137/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_137/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_137/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_137/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00002.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_137/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_137/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00004.png new file mode 100644 index 0000000000..93045c9952 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00005.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_137/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00000.png new file mode 100644 index 0000000000..533981b692 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_approve_5/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_5/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_5/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_5/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00002.png diff --git a/tests/ragger/snapshots/flex/erc721_approve_5/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_approve_5/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00004.png new file mode 100644 index 0000000000..870942f23b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00005.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc721_approve_5/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..66feeb055d Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..31f020e955 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc721_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..66feeb055d Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..31f020e955 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00000.png new file mode 100644 index 0000000000..a692538cb6 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_137/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00004.png new file mode 100644 index 0000000000..3db14db31b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_137/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00006.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_137/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00000.png new file mode 100644 index 0000000000..f7114abc90 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_safeTransferFrom_5/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00004.png new file mode 100644 index 0000000000..da1a95050f Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_5/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00006.png b/tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_5/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc721_safeTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00000.png new file mode 100644 index 0000000000..3868573124 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00003.png new file mode 100644 index 0000000000..6ebb7d15d1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00000.png new file mode 100644 index 0000000000..058addd37e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00003.png new file mode 100644 index 0000000000..73e38ddc76 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00003.png differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_1/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_1/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00000.png new file mode 100644 index 0000000000..8d29aefd95 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00003.png new file mode 100644 index 0000000000..1a28caf59e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_1inch/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/test_1inch/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/flex/test_1inch/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/test_1inch/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00000.png new file mode 100644 index 0000000000..66feeb055d Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_1/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_1/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_1/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00002.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00003.png new file mode 100644 index 0000000000..31f020e955 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_legacy_chainid/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_chainid/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00004.png diff --git a/tests/ragger/snapshots/flex/test_legacy_chainid/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_chainid/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_1/00005.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00000.png new file mode 100644 index 0000000000..a692538cb6 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_137/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_137/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00002.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_137/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_137/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00004.png new file mode 100644 index 0000000000..3db14db31b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_poap/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/test_poap/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00005.png diff --git a/tests/ragger/snapshots/flex/test_poap/00006.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/test_poap/00006.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_137/00006.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00000.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00000.png new file mode 100644 index 0000000000..f7114abc90 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00001.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_5/00001.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00001.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00002.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_5/00002.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00002.png diff --git a/tests/ragger/snapshots/flex/erc721_transferFrom_5/00003.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/erc721_transferFrom_5/00003.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00003.png diff --git a/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00004.png new file mode 100644 index 0000000000..da1a95050f Binary files /dev/null and b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_legacy_send_bsc/00004.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_send_bsc/00004.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00005.png diff --git a/tests/ragger/snapshots/flex/test_legacy_send_bsc/00005.png b/tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_send_bsc/00005.png rename to tests/ragger/snapshots/flex/test_nft_erc721_transferFrom_5/00006.png diff --git a/tests/ragger/snapshots/flex/test_poap/00000.png b/tests/ragger/snapshots/flex/test_poap/00000.png deleted file mode 100644 index 763cb990ea..0000000000 Binary files a/tests/ragger/snapshots/flex/test_poap/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_poap/00001.png b/tests/ragger/snapshots/flex/test_poap/00001.png deleted file mode 100644 index 782f76dc8c..0000000000 Binary files a/tests/ragger/snapshots/flex/test_poap/00001.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_poap/00002.png b/tests/ragger/snapshots/flex/test_poap/00002.png deleted file mode 100644 index aa24355a90..0000000000 Binary files a/tests/ragger/snapshots/flex/test_poap/00002.png and /dev/null differ diff --git a/tests/ragger/snapshots/flex/test_settings/blind_sign/00000.png b/tests/ragger/snapshots/flex/test_settings/blind_sign/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/blind_sign/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/blind_sign/00001.png b/tests/ragger/snapshots/flex/test_settings/blind_sign/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/blind_sign/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/blind_sign/00002.png b/tests/ragger/snapshots/flex/test_settings/blind_sign/00002.png new file mode 100644 index 0000000000..1963ddb85c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/blind_sign/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/blind_sign/00003.png b/tests/ragger/snapshots/flex/test_settings/blind_sign/00003.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/blind_sign/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/debug_token/00000.png b/tests/ragger/snapshots/flex/test_settings/debug_token/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/debug_token/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/debug_token/00001.png b/tests/ragger/snapshots/flex/test_settings/debug_token/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/debug_token/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/debug_token/00002.png b/tests/ragger/snapshots/flex/test_settings/debug_token/00002.png new file mode 100644 index 0000000000..7ca6962532 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/debug_token/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/debug_token/00003.png b/tests/ragger/snapshots/flex/test_settings/debug_token/00003.png new file mode 100644 index 0000000000..1791afe087 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/debug_token/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/debug_token/00004.png b/tests/ragger/snapshots/flex/test_settings/debug_token/00004.png new file mode 100644 index 0000000000..94ecc6a947 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/debug_token/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/debug_token/00005.png b/tests/ragger/snapshots/flex/test_settings/debug_token/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/debug_token/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/eip712_token/00000.png b/tests/ragger/snapshots/flex/test_settings/eip712_token/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/eip712_token/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/eip712_token/00001.png b/tests/ragger/snapshots/flex/test_settings/eip712_token/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/eip712_token/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/eip712_token/00002.png b/tests/ragger/snapshots/flex/test_settings/eip712_token/00002.png new file mode 100644 index 0000000000..7ca6962532 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/eip712_token/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/eip712_token/00003.png b/tests/ragger/snapshots/flex/test_settings/eip712_token/00003.png new file mode 100644 index 0000000000..1791afe087 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/eip712_token/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/eip712_token/00004.png b/tests/ragger/snapshots/flex/test_settings/eip712_token/00004.png new file mode 100644 index 0000000000..e5e08375a4 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/eip712_token/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/eip712_token/00005.png b/tests/ragger/snapshots/flex/test_settings/eip712_token/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/eip712_token/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple1/00000.png b/tests/ragger/snapshots/flex/test_settings/multiple1/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple1/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple1/00001.png b/tests/ragger/snapshots/flex/test_settings/multiple1/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple1/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple1/00002.png b/tests/ragger/snapshots/flex/test_settings/multiple1/00002.png new file mode 100644 index 0000000000..1963ddb85c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple1/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple1/00003.png b/tests/ragger/snapshots/flex/test_settings/multiple1/00003.png new file mode 100644 index 0000000000..7ca6962532 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple1/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple1/00004.png b/tests/ragger/snapshots/flex/test_settings/multiple1/00004.png new file mode 100644 index 0000000000..1791afe087 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple1/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple1/00005.png b/tests/ragger/snapshots/flex/test_settings/multiple1/00005.png new file mode 100644 index 0000000000..94ecc6a947 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple1/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple1/00006.png b/tests/ragger/snapshots/flex/test_settings/multiple1/00006.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple1/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00000.png b/tests/ragger/snapshots/flex/test_settings/multiple2/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple2/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00001.png b/tests/ragger/snapshots/flex/test_settings/multiple2/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple2/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00002.png b/tests/ragger/snapshots/flex/test_settings/multiple2/00002.png new file mode 100644 index 0000000000..1963ddb85c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple2/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00003.png b/tests/ragger/snapshots/flex/test_settings/multiple2/00003.png new file mode 100644 index 0000000000..7ca6962532 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple2/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00004.png b/tests/ragger/snapshots/flex/test_settings/multiple2/00004.png new file mode 100644 index 0000000000..1791afe087 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple2/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00005.png b/tests/ragger/snapshots/flex/test_settings/multiple2/00005.png new file mode 100644 index 0000000000..e5e08375a4 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple2/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00006.png b/tests/ragger/snapshots/flex/test_settings/multiple2/00006.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple2/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple3/00000.png b/tests/ragger/snapshots/flex/test_settings/multiple3/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple3/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple3/00001.png b/tests/ragger/snapshots/flex/test_settings/multiple3/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple3/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple3/00002.png b/tests/ragger/snapshots/flex/test_settings/multiple3/00002.png new file mode 100644 index 0000000000..c7d3888b65 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple3/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple3/00003.png b/tests/ragger/snapshots/flex/test_settings/multiple3/00003.png new file mode 100644 index 0000000000..274cf63801 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple3/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple3/00004.png b/tests/ragger/snapshots/flex/test_settings/multiple3/00004.png new file mode 100644 index 0000000000..e6b59e2f4c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple3/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple3/00005.png b/tests/ragger/snapshots/flex/test_settings/multiple3/00005.png new file mode 100644 index 0000000000..f5b7b978b8 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple3/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple3/00006.png b/tests/ragger/snapshots/flex/test_settings/multiple3/00006.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/multiple3/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/nonce/00000.png b/tests/ragger/snapshots/flex/test_settings/nonce/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/nonce/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/nonce/00001.png b/tests/ragger/snapshots/flex/test_settings/nonce/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/nonce/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/nonce/00002.png b/tests/ragger/snapshots/flex/test_settings/nonce/00002.png new file mode 100644 index 0000000000..7ca6962532 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/nonce/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/nonce/00003.png b/tests/ragger/snapshots/flex/test_settings/nonce/00003.png new file mode 100644 index 0000000000..c4800e4182 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/nonce/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/nonce/00004.png b/tests/ragger/snapshots/flex/test_settings/nonce/00004.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/nonce/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/trusted_name/00000.png b/tests/ragger/snapshots/flex/test_settings/trusted_name/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/trusted_name/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/trusted_name/00001.png b/tests/ragger/snapshots/flex/test_settings/trusted_name/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/trusted_name/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/trusted_name/00002.png b/tests/ragger/snapshots/flex/test_settings/trusted_name/00002.png new file mode 100644 index 0000000000..7ca6962532 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/trusted_name/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/trusted_name/00003.png b/tests/ragger/snapshots/flex/test_settings/trusted_name/00003.png new file mode 100644 index 0000000000..c456ed9c1a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/trusted_name/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/trusted_name/00004.png b/tests/ragger/snapshots/flex/test_settings/trusted_name/00004.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/trusted_name/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/web3_check/00000.png b/tests/ragger/snapshots/flex/test_settings/web3_check/00000.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/web3_check/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/web3_check/00001.png b/tests/ragger/snapshots/flex/test_settings/web3_check/00001.png new file mode 100644 index 0000000000..89cb61a1ac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/web3_check/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/web3_check/00002.png b/tests/ragger/snapshots/flex/test_settings/web3_check/00002.png new file mode 100644 index 0000000000..c7d3888b65 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/web3_check/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/web3_check/00003.png b/tests/ragger/snapshots/flex/test_settings/web3_check/00003.png new file mode 100644 index 0000000000..274cf63801 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/web3_check/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/web3_check/00004.png b/tests/ragger/snapshots/flex/test_settings/web3_check/00004.png new file mode 100644 index 0000000000..e6b59e2f4c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/web3_check/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/web3_check/00005.png b/tests/ragger/snapshots/flex/test_settings/web3_check/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_settings/web3_check/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_legacy_chainid/00000.png b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_chainid/00000.png rename to tests/ragger/snapshots/flex/test_sign_legacy_chainid/00000.png diff --git a/tests/ragger/snapshots/flex/test_legacy_chainid/00001.png b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_chainid/00001.png rename to tests/ragger/snapshots/flex/test_sign_legacy_chainid/00001.png diff --git a/tests/ragger/snapshots/flex/test_legacy_chainid/00002.png b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_chainid/00002.png rename to tests/ragger/snapshots/flex/test_sign_legacy_chainid/00002.png diff --git a/tests/ragger/snapshots/flex/test_legacy_chainid/00003.png b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_chainid/00003.png rename to tests/ragger/snapshots/flex/test_sign_legacy_chainid/00003.png diff --git a/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00004.png b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00005.png b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_sign_legacy_chainid/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_legacy_send_bsc/00000.png b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00000.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_send_bsc/00000.png rename to tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00000.png diff --git a/tests/ragger/snapshots/flex/test_legacy_send_bsc/00001.png b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00001.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_send_bsc/00001.png rename to tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00001.png diff --git a/tests/ragger/snapshots/flex/test_legacy_send_bsc/00002.png b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00002.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_send_bsc/00002.png rename to tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00002.png diff --git a/tests/ragger/snapshots/flex/test_legacy_send_bsc/00003.png b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00003.png similarity index 100% rename from tests/ragger/snapshots/flex/test_legacy_send_bsc/00003.png rename to tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00003.png diff --git a/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00004.png b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00005.png b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_sign_legacy_send_bsc/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_sign_parameter_selector/00006.png b/tests/ragger/snapshots/flex/test_sign_parameter_selector/00006.png index 039eff0472..d17942d01e 100644 Binary files a/tests/ragger/snapshots/flex/test_sign_parameter_selector/00006.png and b/tests/ragger/snapshots/flex/test_sign_parameter_selector/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_sign_parameter_selector/00007.png b/tests/ragger/snapshots/flex/test_sign_parameter_selector/00007.png index a36989ec66..30c604f3dd 100644 Binary files a/tests/ragger/snapshots/flex/test_sign_parameter_selector/00007.png and b/tests/ragger/snapshots/flex/test_sign_parameter_selector/00007.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00000.png new file mode 100644 index 0000000000..08c86e46f3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00001.png new file mode 100644 index 0000000000..e903fe8357 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00002.png new file mode 100644 index 0000000000..fdf1457d2a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00003.png new file mode 100644 index 0000000000..aeb3c483dd Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/warning/00000.png new file mode 100644 index 0000000000..d17942d01e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_benign/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00000.png new file mode 100644 index 0000000000..85fb5ac2ce Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00001.png new file mode 100644 index 0000000000..e903fe8357 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00002.png new file mode 100644 index 0000000000..fdf1457d2a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00003.png new file mode 100644 index 0000000000..aeb3c483dd Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/warning/00000.png new file mode 100644 index 0000000000..d17942d01e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_issue/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00000.png new file mode 100644 index 0000000000..65a7724f47 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00001.png new file mode 100644 index 0000000000..e903fe8357 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00002.png new file mode 100644 index 0000000000..fdf1457d2a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00003.png new file mode 100644 index 0000000000..4e47852074 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/warning/00000.png new file mode 100644 index 0000000000..8ca847f41a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_threat/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00000.png new file mode 100644 index 0000000000..fb6137a256 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00001.png new file mode 100644 index 0000000000..e903fe8357 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00002.png new file mode 100644 index 0000000000..fdf1457d2a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00003.png new file mode 100644 index 0000000000..aeb3c483dd Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/warning/00000.png new file mode 100644 index 0000000000..002e4b6ff1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_blind_sign_warning/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00000.png new file mode 100644 index 0000000000..d61a3257a0 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00001.png new file mode 100644 index 0000000000..19898d45e5 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00002.png new file mode 100644 index 0000000000..fd402468ef Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00003.png new file mode 100644 index 0000000000..8b981d44cc Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00004.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/warning/00000.png new file mode 100644 index 0000000000..a5fefcea79 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00000.png new file mode 100644 index 0000000000..d61a3257a0 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00001.png new file mode 100644 index 0000000000..ba98097c4c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00002.png new file mode 100644 index 0000000000..77ccf81c1a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00003.png new file mode 100644 index 0000000000..2d8bbe340a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/warning/00000.png new file mode 100644 index 0000000000..a5fefcea79 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip191_issue/warning/00000.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 new file mode 100644 index 0000000000..8ca847f41a Binary files /dev/null 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 new file mode 100644 index 0000000000..d7d08264e8 Binary files /dev/null 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 new file mode 100644 index 0000000000..7d202e9138 Binary files /dev/null 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 new file mode 100644 index 0000000000..b1c47066ad Binary files /dev/null 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 new file mode 100644 index 0000000000..8b981d44cc Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00000.png new file mode 100644 index 0000000000..200a42c7a9 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00001.png new file mode 100644 index 0000000000..60ec3f04d5 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00002.png new file mode 100644 index 0000000000..f15e93debd Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00003.png new file mode 100644 index 0000000000..0e2b5aa428 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00004.png new file mode 100644 index 0000000000..fa3c45cffb Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00005.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00006.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00006.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_gcs/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/warning/00000.png new file mode 100644 index 0000000000..002e4b6ff1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_gcs/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..caedb1ee66 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00001.png new file mode 100644 index 0000000000..49f5d63b56 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00002.png new file mode 100644 index 0000000000..10012d8566 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..1e84372137 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png new file mode 100644 index 0000000000..002e4b6ff1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00000.png new file mode 100644 index 0000000000..ec0d8ab258 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00001.png new file mode 100644 index 0000000000..c99e284d88 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00002.png new file mode 100644 index 0000000000..a917445c03 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00003.png new file mode 100644 index 0000000000..4bd528b7c5 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_no_simu/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_opt_in/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_opt_in/00000.png new file mode 100644 index 0000000000..c7d3888b65 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_opt_in/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_opt_in/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_opt_in/00001.png new file mode 100644 index 0000000000..274cf63801 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_opt_in/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00000.png new file mode 100644 index 0000000000..9fc33ce564 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00001.png new file mode 100644 index 0000000000..c99e284d88 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00002.png new file mode 100644 index 0000000000..a917445c03 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00003.png new file mode 100644 index 0000000000..2b912a946a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_benign/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00000.png new file mode 100644 index 0000000000..ec0d8ab258 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00001.png new file mode 100644 index 0000000000..c99e284d88 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00002.png new file mode 100644 index 0000000000..a917445c03 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00003.png new file mode 100644 index 0000000000..4bd528b7c5 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_issue/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00000.png new file mode 100644 index 0000000000..026a9d1d52 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00001.png new file mode 100644 index 0000000000..c99e284d88 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00002.png new file mode 100644 index 0000000000..a917445c03 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00003.png new file mode 100644 index 0000000000..36ec554eac Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/warning/00000.png new file mode 100644 index 0000000000..8ca847f41a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_threat/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00000.png new file mode 100644 index 0000000000..5ddb6dd845 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00001.png new file mode 100644 index 0000000000..c99e284d88 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00002.png new file mode 100644 index 0000000000..a917445c03 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00003.png new file mode 100644 index 0000000000..283276b47e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00004.png new file mode 100644 index 0000000000..be51a9d559 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00005.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00005.png new file mode 100644 index 0000000000..dabe7afea3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/warning/00000.png new file mode 100644 index 0000000000..002e4b6ff1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_sign_warning/warning/00000.png differ diff --git a/tests/ragger/snapshots/nanos/get_pk_1/00000.png b/tests/ragger/snapshots/nanos/test_get_pk_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_1/00000.png rename to tests/ragger/snapshots/nanos/test_get_pk_1/00000.png diff --git a/tests/ragger/snapshots/nanos/get_pk_1/00001.png b/tests/ragger/snapshots/nanos/test_get_pk_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_1/00001.png rename to tests/ragger/snapshots/nanos/test_get_pk_1/00001.png diff --git a/tests/ragger/snapshots/nanos/get_pk_1/00002.png b/tests/ragger/snapshots/nanos/test_get_pk_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_1/00002.png rename to tests/ragger/snapshots/nanos/test_get_pk_1/00002.png diff --git a/tests/ragger/snapshots/nanos/get_pk_1/00003.png b/tests/ragger/snapshots/nanos/test_get_pk_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_1/00003.png rename to tests/ragger/snapshots/nanos/test_get_pk_1/00003.png diff --git a/tests/ragger/snapshots/nanos/get_pk_1/00004.png b/tests/ragger/snapshots/nanos/test_get_pk_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_1/00004.png rename to tests/ragger/snapshots/nanos/test_get_pk_1/00004.png diff --git a/tests/ragger/snapshots/nanos/get_pk_1/00005.png b/tests/ragger/snapshots/nanos/test_get_pk_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_1/00005.png rename to tests/ragger/snapshots/nanos/test_get_pk_1/00005.png diff --git a/tests/ragger/snapshots/nanos/get_pk_137/00000.png b/tests/ragger/snapshots/nanos/test_get_pk_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_137/00000.png rename to tests/ragger/snapshots/nanos/test_get_pk_137/00000.png diff --git a/tests/ragger/snapshots/nanos/get_pk_137/00001.png b/tests/ragger/snapshots/nanos/test_get_pk_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_137/00001.png rename to tests/ragger/snapshots/nanos/test_get_pk_137/00001.png diff --git a/tests/ragger/snapshots/nanos/get_pk_137/00002.png b/tests/ragger/snapshots/nanos/test_get_pk_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_137/00002.png rename to tests/ragger/snapshots/nanos/test_get_pk_137/00002.png diff --git a/tests/ragger/snapshots/nanos/get_pk_137/00003.png b/tests/ragger/snapshots/nanos/test_get_pk_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_137/00003.png rename to tests/ragger/snapshots/nanos/test_get_pk_137/00003.png diff --git a/tests/ragger/snapshots/nanos/get_pk_137/00004.png b/tests/ragger/snapshots/nanos/test_get_pk_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_137/00004.png rename to tests/ragger/snapshots/nanos/test_get_pk_137/00004.png diff --git a/tests/ragger/snapshots/nanos/get_pk_137/00005.png b/tests/ragger/snapshots/nanos/test_get_pk_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_137/00005.png rename to tests/ragger/snapshots/nanos/test_get_pk_137/00005.png diff --git a/tests/ragger/snapshots/nanos/get_pk_2/00000.png b/tests/ragger/snapshots/nanos/test_get_pk_2/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_2/00000.png rename to tests/ragger/snapshots/nanos/test_get_pk_2/00000.png diff --git a/tests/ragger/snapshots/nanos/get_pk_2/00001.png b/tests/ragger/snapshots/nanos/test_get_pk_2/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_2/00001.png rename to tests/ragger/snapshots/nanos/test_get_pk_2/00001.png diff --git a/tests/ragger/snapshots/nanos/get_pk_2/00002.png b/tests/ragger/snapshots/nanos/test_get_pk_2/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_2/00002.png rename to tests/ragger/snapshots/nanos/test_get_pk_2/00002.png diff --git a/tests/ragger/snapshots/nanos/get_pk_2/00003.png b/tests/ragger/snapshots/nanos/test_get_pk_2/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_2/00003.png rename to tests/ragger/snapshots/nanos/test_get_pk_2/00003.png diff --git a/tests/ragger/snapshots/nanos/get_pk_2/00004.png b/tests/ragger/snapshots/nanos/test_get_pk_2/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_2/00004.png rename to tests/ragger/snapshots/nanos/test_get_pk_2/00004.png diff --git a/tests/ragger/snapshots/nanos/get_pk_2/00005.png b/tests/ragger/snapshots/nanos/test_get_pk_2/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_2/00005.png rename to tests/ragger/snapshots/nanos/test_get_pk_2/00005.png diff --git a/tests/ragger/snapshots/nanos/get_pk_5/00000.png b/tests/ragger/snapshots/nanos/test_get_pk_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_5/00000.png rename to tests/ragger/snapshots/nanos/test_get_pk_5/00000.png diff --git a/tests/ragger/snapshots/nanos/get_pk_5/00001.png b/tests/ragger/snapshots/nanos/test_get_pk_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_5/00001.png rename to tests/ragger/snapshots/nanos/test_get_pk_5/00001.png diff --git a/tests/ragger/snapshots/nanos/get_pk_5/00002.png b/tests/ragger/snapshots/nanos/test_get_pk_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_5/00002.png rename to tests/ragger/snapshots/nanos/test_get_pk_5/00002.png diff --git a/tests/ragger/snapshots/nanos/get_pk_5/00003.png b/tests/ragger/snapshots/nanos/test_get_pk_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_5/00003.png rename to tests/ragger/snapshots/nanos/test_get_pk_5/00003.png diff --git a/tests/ragger/snapshots/nanos/get_pk_5/00004.png b/tests/ragger/snapshots/nanos/test_get_pk_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_5/00004.png rename to tests/ragger/snapshots/nanos/test_get_pk_5/00004.png diff --git a/tests/ragger/snapshots/nanos/get_pk_5/00005.png b/tests/ragger/snapshots/nanos/test_get_pk_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_5/00005.png rename to tests/ragger/snapshots/nanos/test_get_pk_5/00005.png diff --git a/tests/ragger/snapshots/nanos/get_pk_None/00000.png b/tests/ragger/snapshots/nanos/test_get_pk_None/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_None/00000.png rename to tests/ragger/snapshots/nanos/test_get_pk_None/00000.png diff --git a/tests/ragger/snapshots/nanos/get_pk_None/00001.png b/tests/ragger/snapshots/nanos/test_get_pk_None/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_None/00001.png rename to tests/ragger/snapshots/nanos/test_get_pk_None/00001.png diff --git a/tests/ragger/snapshots/nanos/get_pk_None/00002.png b/tests/ragger/snapshots/nanos/test_get_pk_None/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_None/00002.png rename to tests/ragger/snapshots/nanos/test_get_pk_None/00002.png diff --git a/tests/ragger/snapshots/nanos/get_pk_None/00003.png b/tests/ragger/snapshots/nanos/test_get_pk_None/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_None/00003.png rename to tests/ragger/snapshots/nanos/test_get_pk_None/00003.png diff --git a/tests/ragger/snapshots/nanos/get_pk_None/00004.png b/tests/ragger/snapshots/nanos/test_get_pk_None/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_None/00004.png rename to tests/ragger/snapshots/nanos/test_get_pk_None/00004.png diff --git a/tests/ragger/snapshots/nanos/get_pk_None/00005.png b/tests/ragger/snapshots/nanos/test_get_pk_None/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_None/00005.png rename to tests/ragger/snapshots/nanos/test_get_pk_None/00005.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_60/00000.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_60/00000.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00000.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_60/00001.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_60/00001.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00001.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_60/00002.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_60/00002.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00002.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_60/00003.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_60/00003.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00003.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_60/00004.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_60/00004.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00004.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_60/00005.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_60/00005.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00005.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_60/00006.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00006.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_60/00006.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_60/00006.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_700/00000.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_700/00000.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00000.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_700/00001.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_700/00001.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00001.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_700/00002.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_700/00002.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00002.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_700/00003.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_700/00003.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00003.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_700/00004.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_700/00004.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00004.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_700/00005.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_700/00005.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00005.png diff --git a/tests/ragger/snapshots/nanos/get_pk_rejected_700/00006.png b/tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00006.png similarity index 100% rename from tests/ragger/snapshots/nanos/get_pk_rejected_700/00006.png rename to tests/ragger/snapshots/nanos/test_get_pk_rejected_700/00006.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00000.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00000.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00000.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00001.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00001.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00001.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00002.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00002.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00002.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00003.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00003.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00003.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00004.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00004.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00004.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00005.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00005.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00005.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00006.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00006.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00006.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00006.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00007.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00007.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00007.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00007.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00008.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00008.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00008.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00008.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00009.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00009.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00009.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00009.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00010.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00010.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00010.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00010.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_chainid/00011.png b/tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00011.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_chainid/00011.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_chainid/00011.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00000.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00000.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00000.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00000.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00001.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00001.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00001.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00001.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00002.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00002.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00002.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00002.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00003.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00003.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00003.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00003.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00004.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00004.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00004.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00004.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00005.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00005.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00005.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00005.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00006.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00006.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00006.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00006.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00007.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00007.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00007.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00007.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00008.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00008.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00008.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00008.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00009.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00009.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00009.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00009.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00010.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00010.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00010.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00010.png diff --git a/tests/ragger/snapshots/nanos/test_legacy_send_bsc/00011.png b/tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00011.png similarity index 100% rename from tests/ragger/snapshots/nanos/test_legacy_send_bsc/00011.png rename to tests/ragger/snapshots/nanos/test_sign_legacy_send_bsc/00011.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00000.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00000.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00001.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00002.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00002.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00003.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00003.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00004.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00004.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00005.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00005.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00006.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00006.png diff --git a/tests/ragger/snapshots/nanosp/test_1inch/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_1inch/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_1inch/00007.png rename to tests/ragger/snapshots/nanosp/test_gcs_1inch/00007.png diff --git a/tests/ragger/snapshots/nanosp/test_gcs_4226/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00000.png new file mode 100644 index 0000000000..526596eff7 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_4226/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_nft/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00001.png rename to tests/ragger/snapshots/nanosp/test_gcs_4226/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_gcs_4226/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00002.png new file mode 100644 index 0000000000..015c7f2dab Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_4226/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_4226/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00003.png new file mode 100644 index 0000000000..0682eba427 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_4226/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_4226/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00004.png new file mode 100644 index 0000000000..72d59c6bee Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_4226/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_4226/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00005.png new file mode 100644 index 0000000000..d4cf4245c0 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_4226/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_1inch/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00006.png rename to tests/ragger/snapshots/nanosp/test_gcs_4226/00006.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_4226/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00007.png rename to tests/ragger/snapshots/nanosp/test_gcs_4226/00007.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00000.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00000.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00001.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nft/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00002.png new file mode 100644 index 0000000000..f9f651a925 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nft/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nft/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00003.png new file mode 100644 index 0000000000..40d12d21e3 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nft/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_nft/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00004.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00004.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00005.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00005.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00006.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00006.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00007.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00007.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00008.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00008.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00008.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00009.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00009.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00009.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00010.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00010.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00010.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00011.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00011.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00011.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00011.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00012.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00012.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00012.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00012.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00013.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00013.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00013.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00013.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00014.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00014.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00014.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00014.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00015.png b/tests/ragger/snapshots/nanosp/test_gcs_nft/00015.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00015.png rename to tests/ragger/snapshots/nanosp/test_gcs_nft/00015.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00000.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00000.png diff --git a/tests/ragger/snapshots/nanox/test_1inch/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00001.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00002.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00002.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00003.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00003.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00004.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00004.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00005.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00005.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00006.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00006.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00007.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00007.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00008.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00008.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00008.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00009.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00009.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00009.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00010.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00010.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00011.png b/tests/ragger/snapshots/nanosp/test_gcs_poap/00011.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00011.png rename to tests/ragger/snapshots/nanosp/test_gcs_poap/00011.png diff --git a/tests/ragger/snapshots/nanosp/test_gcs_proxy/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00000.png new file mode 100644 index 0000000000..935f60b703 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_nft/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00001.png rename to tests/ragger/snapshots/nanosp/test_gcs_proxy/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_gcs_proxy/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00002.png new file mode 100644 index 0000000000..3a7fa2cc1f Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_proxy/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00003.png new file mode 100644 index 0000000000..f65ca1474f Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_nft/00014.png b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00014.png rename to tests/ragger/snapshots/nanosp/test_gcs_proxy/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00009.png b/tests/ragger/snapshots/nanosp/test_gcs_proxy/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00009.png rename to tests/ragger/snapshots/nanosp/test_gcs_proxy/00005.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_1/00000.png b/tests/ragger/snapshots/nanosp/test_get_pk_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_1/00000.png rename to tests/ragger/snapshots/nanosp/test_get_pk_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_1/00001.png b/tests/ragger/snapshots/nanosp/test_get_pk_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_1/00001.png rename to tests/ragger/snapshots/nanosp/test_get_pk_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_1/00002.png b/tests/ragger/snapshots/nanosp/test_get_pk_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_1/00002.png rename to tests/ragger/snapshots/nanosp/test_get_pk_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_1/00003.png b/tests/ragger/snapshots/nanosp/test_get_pk_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_1/00003.png rename to tests/ragger/snapshots/nanosp/test_get_pk_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_137/00000.png b/tests/ragger/snapshots/nanosp/test_get_pk_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_137/00000.png rename to tests/ragger/snapshots/nanosp/test_get_pk_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_137/00001.png b/tests/ragger/snapshots/nanosp/test_get_pk_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_137/00001.png rename to tests/ragger/snapshots/nanosp/test_get_pk_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_137/00002.png b/tests/ragger/snapshots/nanosp/test_get_pk_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_137/00002.png rename to tests/ragger/snapshots/nanosp/test_get_pk_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_137/00003.png b/tests/ragger/snapshots/nanosp/test_get_pk_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_137/00003.png rename to tests/ragger/snapshots/nanosp/test_get_pk_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_2/00000.png b/tests/ragger/snapshots/nanosp/test_get_pk_2/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_2/00000.png rename to tests/ragger/snapshots/nanosp/test_get_pk_2/00000.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_2/00001.png b/tests/ragger/snapshots/nanosp/test_get_pk_2/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_2/00001.png rename to tests/ragger/snapshots/nanosp/test_get_pk_2/00001.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_2/00002.png b/tests/ragger/snapshots/nanosp/test_get_pk_2/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_2/00002.png rename to tests/ragger/snapshots/nanosp/test_get_pk_2/00002.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_2/00003.png b/tests/ragger/snapshots/nanosp/test_get_pk_2/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_2/00003.png rename to tests/ragger/snapshots/nanosp/test_get_pk_2/00003.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_5/00000.png b/tests/ragger/snapshots/nanosp/test_get_pk_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_5/00000.png rename to tests/ragger/snapshots/nanosp/test_get_pk_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_5/00001.png b/tests/ragger/snapshots/nanosp/test_get_pk_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_5/00001.png rename to tests/ragger/snapshots/nanosp/test_get_pk_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_5/00002.png b/tests/ragger/snapshots/nanosp/test_get_pk_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_5/00002.png rename to tests/ragger/snapshots/nanosp/test_get_pk_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_5/00003.png b/tests/ragger/snapshots/nanosp/test_get_pk_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_5/00003.png rename to tests/ragger/snapshots/nanosp/test_get_pk_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_None/00000.png b/tests/ragger/snapshots/nanosp/test_get_pk_None/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_None/00000.png rename to tests/ragger/snapshots/nanosp/test_get_pk_None/00000.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_None/00001.png b/tests/ragger/snapshots/nanosp/test_get_pk_None/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_None/00001.png rename to tests/ragger/snapshots/nanosp/test_get_pk_None/00001.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_None/00002.png b/tests/ragger/snapshots/nanosp/test_get_pk_None/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_None/00002.png rename to tests/ragger/snapshots/nanosp/test_get_pk_None/00002.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_None/00003.png b/tests/ragger/snapshots/nanosp/test_get_pk_None/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_None/00003.png rename to tests/ragger/snapshots/nanosp/test_get_pk_None/00003.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_60/00000.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_60/00000.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00000.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_60/00001.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_60/00001.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00001.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_60/00002.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_60/00002.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00002.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_60/00003.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_60/00003.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00003.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_60/00004.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_60/00004.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_60/00004.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_700/00000.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_700/00000.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00000.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_700/00001.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_700/00001.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00001.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_700/00002.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_700/00002.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00002.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_700/00003.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_700/00003.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00003.png diff --git a/tests/ragger/snapshots/nanosp/get_pk_rejected_700/00004.png b/tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/get_pk_rejected_700/00004.png rename to tests/ragger/snapshots/nanosp/test_get_pk_rejected_700/00004.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00003.png b/tests/ragger/snapshots/nanosp/test_nft/00003.png deleted file mode 100644 index 330755f9fe..0000000000 Binary files a/tests/ragger/snapshots/nanosp/test_nft/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00011.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00011.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00011.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_reject_safeTransferFrom_1/00011.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_1/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_137/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_137/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1-rejected/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeBatchTransferFrom_5/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeBatchTransferFrom_5/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_1/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_1/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_137/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00011.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00011.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00011.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_137/00011.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_safeTransferFrom_5/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00010.png diff --git a/tests/ragger/snapshots/nanosp/test_poap/00011.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00011.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_poap/00011.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_safeTransferFrom_5/00011.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_1/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_137/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_137/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc1155_setApprovalForAll_5/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc1155_setApprovalForAll_5/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_1/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_1/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_1/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_137/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_137/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_137/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_approve_5/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_approve_5/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_approve_5/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1-rejected/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_reject_safeTransferFrom_1/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_1/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_137/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_137/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_safeTransferFrom_5/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_safeTransferFrom_5/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_1/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_1/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_137/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_137/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_setApprovalForAll_5/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_setApprovalForAll_5/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_1/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_137/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_137/00010.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00000.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00000.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00001.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00001.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00002.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00002.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00003.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00003.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00004.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00004.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00005.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00005.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00006.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00006.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00007.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00007.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00008.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00008.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00009.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00009.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00010.png b/tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanosp/erc721_transferFrom_5/00010.png rename to tests/ragger/snapshots/nanosp/test_nft_erc721_transferFrom_5/00010.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00000.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00000.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00000.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00001.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00001.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00002.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00002.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00002.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00003.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00003.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00003.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00004.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00004.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00004.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00005.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00005.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00005.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_chainid/00006.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_chainid/00006.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00006.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00007.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00007.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00007.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_chainid/00007.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00000.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00000.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00000.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00000.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00001.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00001.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00001.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00002.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00002.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00002.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00003.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00003.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00003.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00003.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00004.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00004.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00004.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00004.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00005.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00005.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00005.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00005.png diff --git a/tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00006.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00006.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_legacy_send_bsc/00006.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00006.png diff --git a/tests/ragger/snapshots/nanox/test_1inch/00007.png b/tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00007.png rename to tests/ragger/snapshots/nanosp/test_sign_legacy_send_bsc/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00002.png b/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00002.png deleted file mode 100644 index 1ac2ab0775..0000000000 Binary files a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00002.png and /dev/null differ diff --git a/tests/ragger/snapshots/nanox/test_1inch/00000.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00000.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00000.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00001.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00001.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00001.png diff --git a/tests/ragger/snapshots/nanox/test_1inch/00002.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00002.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00002.png diff --git a/tests/ragger/snapshots/nanox/test_1inch/00003.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00003.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00003.png diff --git a/tests/ragger/snapshots/nanox/test_1inch/00004.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00004.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00004.png diff --git a/tests/ragger/snapshots/nanox/test_1inch/00005.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_1inch/00005.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00005.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00010.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00010.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00006.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00007.png b/tests/ragger/snapshots/nanox/test_gcs_1inch/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00007.png rename to tests/ragger/snapshots/nanox/test_gcs_1inch/00007.png diff --git a/tests/ragger/snapshots/nanox/test_gcs_4226/00000.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00000.png new file mode 100644 index 0000000000..526596eff7 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_4226/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_4226/00001.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00001.png new file mode 100644 index 0000000000..a9deb912be Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_4226/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_4226/00002.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00002.png new file mode 100644 index 0000000000..015c7f2dab Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_4226/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_4226/00003.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00003.png new file mode 100644 index 0000000000..0682eba427 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_4226/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_4226/00004.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00004.png new file mode 100644 index 0000000000..72d59c6bee Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_4226/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_4226/00005.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00005.png new file mode 100644 index 0000000000..d4cf4245c0 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_4226/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_4226/00006.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00006.png new file mode 100644 index 0000000000..63db7647ff Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_4226/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00007.png b/tests/ragger/snapshots/nanox/test_gcs_4226/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00007.png rename to tests/ragger/snapshots/nanox/test_gcs_4226/00007.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00000.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00000.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00000.png diff --git a/tests/ragger/snapshots/nanox/test_gcs_nft/00001.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00001.png new file mode 100644 index 0000000000..a9deb912be Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nft/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nft/00002.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00002.png new file mode 100644 index 0000000000..f9f651a925 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nft/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nft/00003.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00003.png new file mode 100644 index 0000000000..40d12d21e3 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nft/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_nft/00004.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00004.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00004.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00005.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00005.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00005.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00006.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00006.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00006.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00007.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00007.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00007.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00008.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00008.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00008.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00009.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00009.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00009.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00010.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00010.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00010.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00011.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00011.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00011.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00011.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00012.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00012.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00012.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00012.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00013.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00013.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00013.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00013.png diff --git a/tests/ragger/snapshots/nanox/test_gcs_nft/00014.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00014.png new file mode 100644 index 0000000000..63db7647ff Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nft/00014.png differ diff --git a/tests/ragger/snapshots/nanox/test_nft/00015.png b/tests/ragger/snapshots/nanox/test_gcs_nft/00015.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_nft/00015.png rename to tests/ragger/snapshots/nanox/test_gcs_nft/00015.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00000.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00000.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00000.png diff --git a/tests/ragger/snapshots/nanox/test_gcs_poap/00001.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00001.png new file mode 100644 index 0000000000..a9deb912be Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_poap/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_poap/00002.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00002.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00002.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00003.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00003.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00003.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00004.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00004.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00004.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00005.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00005.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00005.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00006.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00006.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00006.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00007.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00007.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00007.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00008.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00008.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00008.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00009.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00009.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00009.png diff --git a/tests/ragger/snapshots/nanox/test_gcs_poap/00010.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00010.png new file mode 100644 index 0000000000..63db7647ff Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_poap/00010.png differ diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00011.png b/tests/ragger/snapshots/nanox/test_gcs_poap/00011.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00011.png rename to tests/ragger/snapshots/nanox/test_gcs_poap/00011.png diff --git a/tests/ragger/snapshots/nanox/test_gcs_proxy/00000.png b/tests/ragger/snapshots/nanox/test_gcs_proxy/00000.png new file mode 100644 index 0000000000..935f60b703 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_proxy/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_proxy/00001.png b/tests/ragger/snapshots/nanox/test_gcs_proxy/00001.png new file mode 100644 index 0000000000..a9deb912be Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_proxy/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_proxy/00002.png b/tests/ragger/snapshots/nanox/test_gcs_proxy/00002.png new file mode 100644 index 0000000000..3a7fa2cc1f Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_proxy/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_proxy/00003.png b/tests/ragger/snapshots/nanox/test_gcs_proxy/00003.png new file mode 100644 index 0000000000..f65ca1474f Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_proxy/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_proxy/00004.png b/tests/ragger/snapshots/nanox/test_gcs_proxy/00004.png new file mode 100644 index 0000000000..63db7647ff Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_proxy/00004.png differ diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00010.png b/tests/ragger/snapshots/nanox/test_gcs_proxy/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00010.png rename to tests/ragger/snapshots/nanox/test_gcs_proxy/00005.png diff --git a/tests/ragger/snapshots/nanox/get_pk_1/00000.png b/tests/ragger/snapshots/nanox/test_get_pk_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_1/00000.png rename to tests/ragger/snapshots/nanox/test_get_pk_1/00000.png diff --git a/tests/ragger/snapshots/nanox/get_pk_1/00001.png b/tests/ragger/snapshots/nanox/test_get_pk_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_1/00001.png rename to tests/ragger/snapshots/nanox/test_get_pk_1/00001.png diff --git a/tests/ragger/snapshots/nanox/get_pk_1/00002.png b/tests/ragger/snapshots/nanox/test_get_pk_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_1/00002.png rename to tests/ragger/snapshots/nanox/test_get_pk_1/00002.png diff --git a/tests/ragger/snapshots/nanox/get_pk_1/00003.png b/tests/ragger/snapshots/nanox/test_get_pk_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_1/00003.png rename to tests/ragger/snapshots/nanox/test_get_pk_1/00003.png diff --git a/tests/ragger/snapshots/nanox/get_pk_137/00000.png b/tests/ragger/snapshots/nanox/test_get_pk_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_137/00000.png rename to tests/ragger/snapshots/nanox/test_get_pk_137/00000.png diff --git a/tests/ragger/snapshots/nanox/get_pk_137/00001.png b/tests/ragger/snapshots/nanox/test_get_pk_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_137/00001.png rename to tests/ragger/snapshots/nanox/test_get_pk_137/00001.png diff --git a/tests/ragger/snapshots/nanox/get_pk_137/00002.png b/tests/ragger/snapshots/nanox/test_get_pk_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_137/00002.png rename to tests/ragger/snapshots/nanox/test_get_pk_137/00002.png diff --git a/tests/ragger/snapshots/nanox/get_pk_137/00003.png b/tests/ragger/snapshots/nanox/test_get_pk_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_137/00003.png rename to tests/ragger/snapshots/nanox/test_get_pk_137/00003.png diff --git a/tests/ragger/snapshots/nanox/get_pk_2/00000.png b/tests/ragger/snapshots/nanox/test_get_pk_2/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_2/00000.png rename to tests/ragger/snapshots/nanox/test_get_pk_2/00000.png diff --git a/tests/ragger/snapshots/nanox/get_pk_2/00001.png b/tests/ragger/snapshots/nanox/test_get_pk_2/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_2/00001.png rename to tests/ragger/snapshots/nanox/test_get_pk_2/00001.png diff --git a/tests/ragger/snapshots/nanox/get_pk_2/00002.png b/tests/ragger/snapshots/nanox/test_get_pk_2/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_2/00002.png rename to tests/ragger/snapshots/nanox/test_get_pk_2/00002.png diff --git a/tests/ragger/snapshots/nanox/get_pk_2/00003.png b/tests/ragger/snapshots/nanox/test_get_pk_2/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_2/00003.png rename to tests/ragger/snapshots/nanox/test_get_pk_2/00003.png diff --git a/tests/ragger/snapshots/nanox/get_pk_5/00000.png b/tests/ragger/snapshots/nanox/test_get_pk_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_5/00000.png rename to tests/ragger/snapshots/nanox/test_get_pk_5/00000.png diff --git a/tests/ragger/snapshots/nanox/get_pk_5/00001.png b/tests/ragger/snapshots/nanox/test_get_pk_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_5/00001.png rename to tests/ragger/snapshots/nanox/test_get_pk_5/00001.png diff --git a/tests/ragger/snapshots/nanox/get_pk_5/00002.png b/tests/ragger/snapshots/nanox/test_get_pk_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_5/00002.png rename to tests/ragger/snapshots/nanox/test_get_pk_5/00002.png diff --git a/tests/ragger/snapshots/nanox/get_pk_5/00003.png b/tests/ragger/snapshots/nanox/test_get_pk_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_5/00003.png rename to tests/ragger/snapshots/nanox/test_get_pk_5/00003.png diff --git a/tests/ragger/snapshots/nanox/get_pk_None/00000.png b/tests/ragger/snapshots/nanox/test_get_pk_None/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_None/00000.png rename to tests/ragger/snapshots/nanox/test_get_pk_None/00000.png diff --git a/tests/ragger/snapshots/nanox/get_pk_None/00001.png b/tests/ragger/snapshots/nanox/test_get_pk_None/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_None/00001.png rename to tests/ragger/snapshots/nanox/test_get_pk_None/00001.png diff --git a/tests/ragger/snapshots/nanox/get_pk_None/00002.png b/tests/ragger/snapshots/nanox/test_get_pk_None/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_None/00002.png rename to tests/ragger/snapshots/nanox/test_get_pk_None/00002.png diff --git a/tests/ragger/snapshots/nanox/get_pk_None/00003.png b/tests/ragger/snapshots/nanox/test_get_pk_None/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_None/00003.png rename to tests/ragger/snapshots/nanox/test_get_pk_None/00003.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_60/00000.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_60/00000.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00000.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_60/00001.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_60/00001.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00001.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_60/00002.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_60/00002.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00002.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_60/00003.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_60/00003.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00003.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_60/00004.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_60/00004.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_60/00004.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_700/00000.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_700/00000.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00000.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_700/00001.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_700/00001.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00001.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_700/00002.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_700/00002.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00002.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_700/00003.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_700/00003.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00003.png diff --git a/tests/ragger/snapshots/nanox/get_pk_rejected_700/00004.png b/tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/get_pk_rejected_700/00004.png rename to tests/ragger/snapshots/nanox/test_get_pk_rejected_700/00004.png diff --git a/tests/ragger/snapshots/nanox/test_nft/00002.png b/tests/ragger/snapshots/nanox/test_nft/00002.png deleted file mode 100644 index 1ac2ab0775..0000000000 Binary files a/tests/ragger/snapshots/nanox/test_nft/00002.png and /dev/null differ diff --git a/tests/ragger/snapshots/nanox/test_nft/00003.png b/tests/ragger/snapshots/nanox/test_nft/00003.png deleted file mode 100644 index 330755f9fe..0000000000 Binary files a/tests/ragger/snapshots/nanox/test_nft/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanosp/test_nft/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanosp/test_nft/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00010.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00011.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00011.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00011.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_reject_safeTransferFrom_1/00011.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_1/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_137/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_137/00010.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeBatchTransferFrom_5/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeBatchTransferFrom_5/00010.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_1/00010.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00010.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00011.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00011.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00011.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_137/00011.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00010.png diff --git a/tests/ragger/snapshots/nanox/test_poap/00011.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00011.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_poap/00011.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_safeTransferFrom_5/00011.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00008.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_137/00009.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00000.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00003.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00006.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00007.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc1155_setApprovalForAll_5/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc1155_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_1/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_1/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_1/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_137/00010.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_137/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_137/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_approve_5/00010.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_approve_5/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_approve_5/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_reject_safeTransferFrom_1/00010.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_137/00010.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00010.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_safeTransferFrom_5/00010.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_137/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_setApprovalForAll_5/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00010.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_1/00009.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_1/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_1/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00009.png diff --git a/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00010.png new file mode 100644 index 0000000000..a58590b988 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_137/00010.png differ diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00000.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00000.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00000.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00001.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00001.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00001.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_137/00002.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_137/00002.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00002.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00003.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00003.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00003.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00004.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00004.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00004.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00005.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00005.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00005.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00006.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00006.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00006.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00007.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00007.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00007.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00007.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00008.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00008.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00008.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00008.png diff --git a/tests/ragger/snapshots/nanox/erc721_transferFrom_5/00009.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00009.png similarity index 100% rename from tests/ragger/snapshots/nanox/erc721_transferFrom_5/00009.png rename to tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00009.png diff --git a/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00010.png b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00010.png new file mode 100644 index 0000000000..a58590b988 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_nft_erc721_transferFrom_5/00010.png differ diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00000.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00000.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00000.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00001.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00001.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00001.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00002.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00002.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00002.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00003.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00003.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00003.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00004.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00004.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00004.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00005.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00005.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00005.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_chainid/00006.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_chainid/00006.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00006.png diff --git a/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00007.png b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00007.png new file mode 100644 index 0000000000..a58590b988 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_sign_legacy_chainid/00007.png differ diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00000.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00000.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00000.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00000.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00001.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00001.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00001.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00001.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00002.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00002.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00002.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00002.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00003.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00003.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00003.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00003.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00004.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00004.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00004.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00004.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00005.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00005.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00005.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00005.png diff --git a/tests/ragger/snapshots/nanox/test_legacy_send_bsc/00006.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00006.png similarity index 100% rename from tests/ragger/snapshots/nanox/test_legacy_send_bsc/00006.png rename to tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00006.png diff --git a/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00007.png b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00007.png new file mode 100644 index 0000000000..a58590b988 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_sign_legacy_send_bsc/00007.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00000.png deleted file mode 100644 index f1b9f80213..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00003.png deleted file mode 100644 index 15ac71abf0..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00000.png b/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00000.png deleted file mode 100644 index 5afbca6774..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00003.png b/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00003.png deleted file mode 100644 index 2c45d20022..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00000.png b/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00000.png deleted file mode 100644 index 6287c4f109..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00003.png b/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00003.png deleted file mode 100644 index 48a5f5b541..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00000.png deleted file mode 100644 index 9a0e1460eb..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00003.png deleted file mode 100644 index 205e02ad37..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00000.png deleted file mode 100644 index 9a0e1460eb..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00003.png deleted file mode 100644 index 205e02ad37..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00000.png deleted file mode 100644 index b8f06d49c7..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00003.png deleted file mode 100644 index 1e9a74f2f8..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00000.png deleted file mode 100644 index 111fb39621..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00003.png deleted file mode 100644 index 5ec95690fe..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00000.png deleted file mode 100644 index 7838b753be..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00003.png deleted file mode 100644 index ed27647caf..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00000.png deleted file mode 100644 index ad2d747987..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00003.png deleted file mode 100644 index 13a8a1738e..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00000.png deleted file mode 100644 index e15cfa60ea..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00003.png deleted file mode 100644 index 33991241e9..0000000000 Binary files a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_1/00000.png b/tests/ragger/snapshots/stax/erc721_approve_1/00000.png deleted file mode 100644 index 7838b753be..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_approve_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_1/00003.png b/tests/ragger/snapshots/stax/erc721_approve_1/00003.png deleted file mode 100644 index ed27647caf..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_approve_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_137/00000.png b/tests/ragger/snapshots/stax/erc721_approve_137/00000.png deleted file mode 100644 index ad2d747987..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_approve_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_137/00003.png b/tests/ragger/snapshots/stax/erc721_approve_137/00003.png deleted file mode 100644 index 13a8a1738e..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_approve_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_5/00000.png b/tests/ragger/snapshots/stax/erc721_approve_5/00000.png deleted file mode 100644 index e15cfa60ea..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_approve_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_5/00003.png b/tests/ragger/snapshots/stax/erc721_approve_5/00003.png deleted file mode 100644 index 33991241e9..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_approve_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00000.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00000.png deleted file mode 100644 index 9a0e1460eb..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00003.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00003.png deleted file mode 100644 index 205e02ad37..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00000.png deleted file mode 100644 index 9a0e1460eb..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00003.png deleted file mode 100644 index 205e02ad37..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00000.png deleted file mode 100644 index b8f06d49c7..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00003.png deleted file mode 100644 index 1e9a74f2f8..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00000.png deleted file mode 100644 index 111fb39621..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00003.png deleted file mode 100644 index 5ec95690fe..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00000.png deleted file mode 100644 index 7838b753be..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00003.png deleted file mode 100644 index ed27647caf..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00000.png deleted file mode 100644 index ad2d747987..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00003.png deleted file mode 100644 index 13a8a1738e..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00000.png deleted file mode 100644 index e15cfa60ea..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00003.png deleted file mode 100644 index 33991241e9..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00000.png b/tests/ragger/snapshots/stax/erc721_transferFrom_1/00000.png deleted file mode 100644 index 9a0e1460eb..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00003.png b/tests/ragger/snapshots/stax/erc721_transferFrom_1/00003.png deleted file mode 100644 index 205e02ad37..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00000.png b/tests/ragger/snapshots/stax/erc721_transferFrom_137/00000.png deleted file mode 100644 index b8f06d49c7..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00003.png b/tests/ragger/snapshots/stax/erc721_transferFrom_137/00003.png deleted file mode 100644 index 1e9a74f2f8..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00000.png b/tests/ragger/snapshots/stax/erc721_transferFrom_5/00000.png deleted file mode 100644 index 111fb39621..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00003.png b/tests/ragger/snapshots/stax/erc721_transferFrom_5/00003.png deleted file mode 100644 index 5ec95690fe..0000000000 Binary files a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_1inch/00000.png b/tests/ragger/snapshots/stax/test_1inch/00000.png deleted file mode 100644 index 7034dc469f..0000000000 Binary files a/tests/ragger/snapshots/stax/test_1inch/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_1inch/00001.png b/tests/ragger/snapshots/stax/test_1inch/00001.png deleted file mode 100644 index 0560e47b7d..0000000000 Binary files a/tests/ragger/snapshots/stax/test_1inch/00001.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign/00000.png b/tests/ragger/snapshots/stax/test_blind_sign/00000.png index 0463721b10..a9cb3a2f07 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign/00000.png and b/tests/ragger/snapshots/stax/test_blind_sign/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign/00001.png b/tests/ragger/snapshots/stax/test_blind_sign/00001.png index e993bf9987..1898206ed9 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign/00001.png and b/tests/ragger/snapshots/stax/test_blind_sign/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign/00002.png b/tests/ragger/snapshots/stax/test_blind_sign/00002.png index 1898206ed9..fcccc77dfe 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign/00002.png and b/tests/ragger/snapshots/stax/test_blind_sign/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign/00003.png b/tests/ragger/snapshots/stax/test_blind_sign/00003.png index fcccc77dfe..3c89d74c4c 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign/00003.png and b/tests/ragger/snapshots/stax/test_blind_sign/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign/00004.png b/tests/ragger/snapshots/stax/test_blind_sign/00004.png index 3c89d74c4c..392165d4fc 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign/00004.png and b/tests/ragger/snapshots/stax/test_blind_sign/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign/00005.png b/tests/ragger/snapshots/stax/test_blind_sign/00005.png index 392165d4fc..339db1b45c 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign/00005.png and b/tests/ragger/snapshots/stax/test_blind_sign/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign/warning/00000.png b/tests/ragger/snapshots/stax/test_blind_sign/warning/00000.png new file mode 100644 index 0000000000..e7a78b5be3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_blind_sign/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00000.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00000.png index 0463721b10..a9cb3a2f07 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00000.png and b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00001.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00001.png index e993bf9987..e1effabb54 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00001.png and b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00002.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00002.png index e1effabb54..fcccc77dfe 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00002.png and b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00003.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00003.png index fcccc77dfe..3c89d74c4c 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00003.png and b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00004.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00004.png index 3c89d74c4c..392165d4fc 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00004.png and b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00005.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00005.png index 392165d4fc..339db1b45c 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00005.png and b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_nonzero/warning/00000.png b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/warning/00000.png new file mode 100644 index 0000000000..e7a78b5be3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_blind_sign_nonzero/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00000.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00000.png index 0463721b10..a9cb3a2f07 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00000.png and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00001.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00001.png index e993bf9987..1898206ed9 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00001.png and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00002.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00002.png index 1898206ed9..fcccc77dfe 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00002.png and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00003.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00003.png index fcccc77dfe..3c89d74c4c 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00003.png and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00004.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00004.png index 3c89d74c4c..abc9677f73 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00004.png and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00005.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00005.png index abc9677f73..2b66970014 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00005.png and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00006.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00006.png index 2b66970014..339db1b45c 100644 Binary files a/tests/ragger/snapshots/stax/test_blind_sign_rejected/00006.png and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_blind_sign_rejected/warning/00000.png b/tests/ragger/snapshots/stax/test_blind_sign_rejected/warning/00000.png new file mode 100644 index 0000000000..e7a78b5be3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_blind_sign_rejected/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_1inch/00000.png b/tests/ragger/snapshots/stax/test_gcs_1inch/00000.png new file mode 100644 index 0000000000..e55c83d75a Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_1inch/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_1inch/00001.png b/tests/ragger/snapshots/stax/test_gcs_1inch/00001.png new file mode 100644 index 0000000000..98168961aa Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_1inch/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_1inch/00002.png b/tests/ragger/snapshots/stax/test_gcs_1inch/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/test_1inch/00002.png rename to tests/ragger/snapshots/stax/test_gcs_1inch/00002.png diff --git a/tests/ragger/snapshots/stax/test_1inch/00003.png b/tests/ragger/snapshots/stax/test_gcs_1inch/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/test_1inch/00003.png rename to tests/ragger/snapshots/stax/test_gcs_1inch/00003.png diff --git a/tests/ragger/snapshots/stax/test_1inch/00004.png b/tests/ragger/snapshots/stax/test_gcs_1inch/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/test_1inch/00004.png rename to tests/ragger/snapshots/stax/test_gcs_1inch/00004.png diff --git a/tests/ragger/snapshots/stax/test_gcs_4226/00000.png b/tests/ragger/snapshots/stax/test_gcs_4226/00000.png new file mode 100644 index 0000000000..62b1d0e83d Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_4226/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_4226/00001.png b/tests/ragger/snapshots/stax/test_gcs_4226/00001.png new file mode 100644 index 0000000000..c274e99ff7 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_4226/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_4226/00002.png b/tests/ragger/snapshots/stax/test_gcs_4226/00002.png new file mode 100644 index 0000000000..9092ac0955 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_4226/00002.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00004.png b/tests/ragger/snapshots/stax/test_gcs_4226/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00004.png rename to tests/ragger/snapshots/stax/test_gcs_4226/00003.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00005.png b/tests/ragger/snapshots/stax/test_gcs_4226/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00005.png rename to tests/ragger/snapshots/stax/test_gcs_4226/00004.png diff --git a/tests/ragger/snapshots/stax/test_gcs_nft/00000.png b/tests/ragger/snapshots/stax/test_gcs_nft/00000.png new file mode 100644 index 0000000000..5ddddac791 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nft/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nft/00001.png b/tests/ragger/snapshots/stax/test_gcs_nft/00001.png new file mode 100644 index 0000000000..25570f1376 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nft/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nft/00002.png b/tests/ragger/snapshots/stax/test_gcs_nft/00002.png new file mode 100644 index 0000000000..b57d8c747f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nft/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nft/00003.png b/tests/ragger/snapshots/stax/test_gcs_nft/00003.png new file mode 100644 index 0000000000..2f452c0292 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nft/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_nft/00004.png b/tests/ragger/snapshots/stax/test_gcs_nft/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/test_nft/00004.png rename to tests/ragger/snapshots/stax/test_gcs_nft/00004.png diff --git a/tests/ragger/snapshots/stax/test_nft/00005.png b/tests/ragger/snapshots/stax/test_gcs_nft/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/test_nft/00005.png rename to tests/ragger/snapshots/stax/test_gcs_nft/00005.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/stax/test_gcs_nft/00006.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/stax/test_gcs_nft/00006.png diff --git a/tests/ragger/snapshots/stax/test_gcs_poap/00000.png b/tests/ragger/snapshots/stax/test_gcs_poap/00000.png new file mode 100644 index 0000000000..80cfac21d4 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_poap/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_poap/00001.png b/tests/ragger/snapshots/stax/test_gcs_poap/00001.png new file mode 100644 index 0000000000..91237f1b84 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_poap/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_poap/00002.png b/tests/ragger/snapshots/stax/test_gcs_poap/00002.png new file mode 100644 index 0000000000..e59f27d25f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_poap/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_poap/00003.png b/tests/ragger/snapshots/stax/test_gcs_poap/00003.png new file mode 100644 index 0000000000..7d12ffb070 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_poap/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_poap/00004.png b/tests/ragger/snapshots/stax/test_gcs_poap/00004.png new file mode 100644 index 0000000000..60d7053465 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_poap/00004.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00004.png b/tests/ragger/snapshots/stax/test_gcs_poap/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00004.png rename to tests/ragger/snapshots/stax/test_gcs_poap/00005.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00006.png b/tests/ragger/snapshots/stax/test_gcs_poap/00006.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00006.png rename to tests/ragger/snapshots/stax/test_gcs_poap/00006.png diff --git a/tests/ragger/snapshots/stax/test_gcs_proxy/00000.png b/tests/ragger/snapshots/stax/test_gcs_proxy/00000.png new file mode 100644 index 0000000000..63689b7e30 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_proxy/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_proxy/00001.png b/tests/ragger/snapshots/stax/test_gcs_proxy/00001.png new file mode 100644 index 0000000000..64e0a8a4cc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_proxy/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_proxy/00002.png b/tests/ragger/snapshots/stax/test_gcs_proxy/00002.png new file mode 100644 index 0000000000..88e70e3356 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_proxy/00002.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00004.png b/tests/ragger/snapshots/stax/test_gcs_proxy/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00004.png rename to tests/ragger/snapshots/stax/test_gcs_proxy/00003.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00005.png b/tests/ragger/snapshots/stax/test_gcs_proxy/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00005.png rename to tests/ragger/snapshots/stax/test_gcs_proxy/00004.png diff --git a/tests/ragger/snapshots/stax/get_pk_1/00000.png b/tests/ragger/snapshots/stax/test_get_pk_1/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_1/00000.png rename to tests/ragger/snapshots/stax/test_get_pk_1/00000.png diff --git a/tests/ragger/snapshots/stax/get_pk_1/00001.png b/tests/ragger/snapshots/stax/test_get_pk_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_1/00001.png rename to tests/ragger/snapshots/stax/test_get_pk_1/00001.png diff --git a/tests/ragger/snapshots/stax/get_pk_1/00002.png b/tests/ragger/snapshots/stax/test_get_pk_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_1/00002.png rename to tests/ragger/snapshots/stax/test_get_pk_1/00002.png diff --git a/tests/ragger/snapshots/stax/get_pk_1/00003.png b/tests/ragger/snapshots/stax/test_get_pk_1/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_1/00003.png rename to tests/ragger/snapshots/stax/test_get_pk_1/00003.png diff --git a/tests/ragger/snapshots/stax/get_pk_137/00000.png b/tests/ragger/snapshots/stax/test_get_pk_137/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_137/00000.png rename to tests/ragger/snapshots/stax/test_get_pk_137/00000.png diff --git a/tests/ragger/snapshots/stax/get_pk_137/00001.png b/tests/ragger/snapshots/stax/test_get_pk_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_137/00001.png rename to tests/ragger/snapshots/stax/test_get_pk_137/00001.png diff --git a/tests/ragger/snapshots/stax/get_pk_137/00002.png b/tests/ragger/snapshots/stax/test_get_pk_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_137/00002.png rename to tests/ragger/snapshots/stax/test_get_pk_137/00002.png diff --git a/tests/ragger/snapshots/stax/get_pk_137/00003.png b/tests/ragger/snapshots/stax/test_get_pk_137/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_137/00003.png rename to tests/ragger/snapshots/stax/test_get_pk_137/00003.png diff --git a/tests/ragger/snapshots/stax/get_pk_2/00000.png b/tests/ragger/snapshots/stax/test_get_pk_2/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_2/00000.png rename to tests/ragger/snapshots/stax/test_get_pk_2/00000.png diff --git a/tests/ragger/snapshots/stax/get_pk_2/00001.png b/tests/ragger/snapshots/stax/test_get_pk_2/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_2/00001.png rename to tests/ragger/snapshots/stax/test_get_pk_2/00001.png diff --git a/tests/ragger/snapshots/stax/get_pk_2/00002.png b/tests/ragger/snapshots/stax/test_get_pk_2/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_2/00002.png rename to tests/ragger/snapshots/stax/test_get_pk_2/00002.png diff --git a/tests/ragger/snapshots/stax/get_pk_2/00003.png b/tests/ragger/snapshots/stax/test_get_pk_2/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_2/00003.png rename to tests/ragger/snapshots/stax/test_get_pk_2/00003.png diff --git a/tests/ragger/snapshots/stax/get_pk_5/00000.png b/tests/ragger/snapshots/stax/test_get_pk_5/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_5/00000.png rename to tests/ragger/snapshots/stax/test_get_pk_5/00000.png diff --git a/tests/ragger/snapshots/stax/get_pk_5/00001.png b/tests/ragger/snapshots/stax/test_get_pk_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_5/00001.png rename to tests/ragger/snapshots/stax/test_get_pk_5/00001.png diff --git a/tests/ragger/snapshots/stax/get_pk_5/00002.png b/tests/ragger/snapshots/stax/test_get_pk_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_5/00002.png rename to tests/ragger/snapshots/stax/test_get_pk_5/00002.png diff --git a/tests/ragger/snapshots/stax/get_pk_5/00003.png b/tests/ragger/snapshots/stax/test_get_pk_5/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_5/00003.png rename to tests/ragger/snapshots/stax/test_get_pk_5/00003.png diff --git a/tests/ragger/snapshots/stax/get_pk_None/00000.png b/tests/ragger/snapshots/stax/test_get_pk_None/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_None/00000.png rename to tests/ragger/snapshots/stax/test_get_pk_None/00000.png diff --git a/tests/ragger/snapshots/stax/get_pk_None/00001.png b/tests/ragger/snapshots/stax/test_get_pk_None/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_None/00001.png rename to tests/ragger/snapshots/stax/test_get_pk_None/00001.png diff --git a/tests/ragger/snapshots/stax/get_pk_None/00002.png b/tests/ragger/snapshots/stax/test_get_pk_None/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_None/00002.png rename to tests/ragger/snapshots/stax/test_get_pk_None/00002.png diff --git a/tests/ragger/snapshots/stax/get_pk_None/00003.png b/tests/ragger/snapshots/stax/test_get_pk_None/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_None/00003.png rename to tests/ragger/snapshots/stax/test_get_pk_None/00003.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_60/00000.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_60/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_60/00000.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_60/00000.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_60/00001.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_60/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_60/00001.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_60/00001.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_60/00002.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_60/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_60/00002.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_60/00002.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_60/00003.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_60/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_60/00003.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_60/00003.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_700/00000.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_700/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_700/00000.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_700/00000.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_700/00001.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_700/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_700/00001.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_700/00001.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_700/00002.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_700/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_700/00002.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_700/00002.png diff --git a/tests/ragger/snapshots/stax/get_pk_rejected_700/00003.png b/tests/ragger/snapshots/stax/test_get_pk_rejected_700/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/get_pk_rejected_700/00003.png rename to tests/ragger/snapshots/stax/test_get_pk_rejected_700/00003.png diff --git a/tests/ragger/snapshots/stax/test_nft/00000.png b/tests/ragger/snapshots/stax/test_nft/00000.png deleted file mode 100644 index b0958508a7..0000000000 Binary files a/tests/ragger/snapshots/stax/test_nft/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_nft/00001.png b/tests/ragger/snapshots/stax/test_nft/00001.png deleted file mode 100644 index 9c132ca352..0000000000 Binary files a/tests/ragger/snapshots/stax/test_nft/00001.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_nft/00002.png b/tests/ragger/snapshots/stax/test_nft/00002.png deleted file mode 100644 index 5c983c9d1c..0000000000 Binary files a/tests/ragger/snapshots/stax/test_nft/00002.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_nft/00003.png b/tests/ragger/snapshots/stax/test_nft/00003.png deleted file mode 100644 index 2a281fb07a..0000000000 Binary files a/tests/ragger/snapshots/stax/test_nft/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..b0546e1711 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..85196cb3d3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft/00006.png b/tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/stax/test_nft/00006.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00000.png new file mode 100644 index 0000000000..c621eab267 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_1/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00003.png new file mode 100644 index 0000000000..dd86b7bf78 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00000.png new file mode 100644 index 0000000000..70a60f2915 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_137/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00003.png new file mode 100644 index 0000000000..ba9fb9e63e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00000.png new file mode 100644 index 0000000000..ebad9b409e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeBatchTransferFrom_5/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00003.png new file mode 100644 index 0000000000..bbbcfd92e2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeBatchTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..b0546e1711 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..85196cb3d3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00000.png new file mode 100644 index 0000000000..92aaf8aab4 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00003.png new file mode 100644 index 0000000000..d82e3bb4da Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00000.png new file mode 100644 index 0000000000..9a07fa7062 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00003.png new file mode 100644 index 0000000000..b747477942 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00000.png new file mode 100644 index 0000000000..433c5eca15 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00003.png new file mode 100644 index 0000000000..b3ce2ae721 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_1/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_1/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00000.png new file mode 100644 index 0000000000..eb12e3f84c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00003.png new file mode 100644 index 0000000000..fe3239272b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_137/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_137/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_approve_1/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_1/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00000.png new file mode 100644 index 0000000000..80269f94a2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc1155_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00003.png new file mode 100644 index 0000000000..7e6a787b7e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_5/00004.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_5/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_approve_137/00005.png b/tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_137/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc1155_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00000.png new file mode 100644 index 0000000000..433c5eca15 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_1/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_1/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_approve_1/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_1/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00003.png new file mode 100644 index 0000000000..b3ce2ae721 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_approve_5/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_5/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00000.png new file mode 100644 index 0000000000..eb12e3f84c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_137/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_137/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_approve_137/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_137/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00003.png new file mode 100644 index 0000000000..fe3239272b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_137/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00000.png new file mode 100644 index 0000000000..80269f94a2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_approve_5/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_5/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_approve_5/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_approve_5/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00003.png new file mode 100644 index 0000000000..7e6a787b7e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_approve_5/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..b0546e1711 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..85196cb3d3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1-rejected/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00006.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_reject_safeTransferFrom_1/00006.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..b0546e1711 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_1/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..85196cb3d3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00000.png new file mode 100644 index 0000000000..92aaf8aab4 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_137/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00003.png new file mode 100644 index 0000000000..d82e3bb4da Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_137/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00000.png new file mode 100644 index 0000000000..9a07fa7062 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_safeTransferFrom_5/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00003.png new file mode 100644 index 0000000000..b747477942 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_safeTransferFrom_5/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00000.png new file mode 100644 index 0000000000..433c5eca15 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_1/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00003.png new file mode 100644 index 0000000000..b3ce2ae721 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_1/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_1/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00000.png new file mode 100644 index 0000000000..eb12e3f84c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_137/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00003.png new file mode 100644 index 0000000000..fe3239272b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_137/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_137/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_137/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00000.png new file mode 100644 index 0000000000..80269f94a2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_setApprovalForAll_5/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00003.png new file mode 100644 index 0000000000..7e6a787b7e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00003.png differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_5/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00004.png diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_5/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_setApprovalForAll_5/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00000.png new file mode 100644 index 0000000000..b0546e1711 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_1/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_1/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_1/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00003.png new file mode 100644 index 0000000000..85196cb3d3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_legacy_chainid/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_chainid/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00004.png diff --git a/tests/ragger/snapshots/stax/test_legacy_chainid/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_chainid/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_1/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00000.png new file mode 100644 index 0000000000..92aaf8aab4 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_137/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_137/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_137/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00003.png new file mode 100644 index 0000000000..d82e3bb4da Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_legacy_send_bsc/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_send_bsc/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00004.png diff --git a/tests/ragger/snapshots/stax/test_legacy_send_bsc/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_send_bsc/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_137/00005.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00000.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00000.png new file mode 100644 index 0000000000..9a07fa7062 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00001.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_5/00001.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00001.png diff --git a/tests/ragger/snapshots/stax/erc721_transferFrom_5/00002.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/erc721_transferFrom_5/00002.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00002.png diff --git a/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00003.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00003.png new file mode 100644 index 0000000000..b747477942 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_poap/00004.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/test_poap/00004.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00004.png diff --git a/tests/ragger/snapshots/stax/test_poap/00005.png b/tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/test_poap/00005.png rename to tests/ragger/snapshots/stax/test_nft_erc721_transferFrom_5/00005.png diff --git a/tests/ragger/snapshots/stax/test_poap/00000.png b/tests/ragger/snapshots/stax/test_poap/00000.png deleted file mode 100644 index 751240cb5c..0000000000 Binary files a/tests/ragger/snapshots/stax/test_poap/00000.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_poap/00001.png b/tests/ragger/snapshots/stax/test_poap/00001.png deleted file mode 100644 index f73962481c..0000000000 Binary files a/tests/ragger/snapshots/stax/test_poap/00001.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_poap/00002.png b/tests/ragger/snapshots/stax/test_poap/00002.png deleted file mode 100644 index 829c038b45..0000000000 Binary files a/tests/ragger/snapshots/stax/test_poap/00002.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_poap/00003.png b/tests/ragger/snapshots/stax/test_poap/00003.png deleted file mode 100644 index 40dc555ff4..0000000000 Binary files a/tests/ragger/snapshots/stax/test_poap/00003.png and /dev/null differ diff --git a/tests/ragger/snapshots/stax/test_settings/blind_sign/00000.png b/tests/ragger/snapshots/stax/test_settings/blind_sign/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/blind_sign/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/blind_sign/00001.png b/tests/ragger/snapshots/stax/test_settings/blind_sign/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/blind_sign/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/blind_sign/00002.png b/tests/ragger/snapshots/stax/test_settings/blind_sign/00002.png new file mode 100644 index 0000000000..d82692eefc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/blind_sign/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/blind_sign/00003.png b/tests/ragger/snapshots/stax/test_settings/blind_sign/00003.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/blind_sign/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/debug_token/00000.png b/tests/ragger/snapshots/stax/test_settings/debug_token/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/debug_token/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/debug_token/00001.png b/tests/ragger/snapshots/stax/test_settings/debug_token/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/debug_token/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/debug_token/00002.png b/tests/ragger/snapshots/stax/test_settings/debug_token/00002.png new file mode 100644 index 0000000000..63fa5b49cd Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/debug_token/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/debug_token/00003.png b/tests/ragger/snapshots/stax/test_settings/debug_token/00003.png new file mode 100644 index 0000000000..440d5e48cc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/debug_token/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/debug_token/00004.png b/tests/ragger/snapshots/stax/test_settings/debug_token/00004.png new file mode 100644 index 0000000000..8d8f509706 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/debug_token/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/debug_token/00005.png b/tests/ragger/snapshots/stax/test_settings/debug_token/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/debug_token/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/eip712_token/00000.png b/tests/ragger/snapshots/stax/test_settings/eip712_token/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/eip712_token/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/eip712_token/00001.png b/tests/ragger/snapshots/stax/test_settings/eip712_token/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/eip712_token/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/eip712_token/00002.png b/tests/ragger/snapshots/stax/test_settings/eip712_token/00002.png new file mode 100644 index 0000000000..63fa5b49cd Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/eip712_token/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/eip712_token/00003.png b/tests/ragger/snapshots/stax/test_settings/eip712_token/00003.png new file mode 100644 index 0000000000..3bd5f5f1cc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/eip712_token/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/eip712_token/00004.png b/tests/ragger/snapshots/stax/test_settings/eip712_token/00004.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/eip712_token/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00000.png b/tests/ragger/snapshots/stax/test_settings/multiple1/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple1/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00001.png b/tests/ragger/snapshots/stax/test_settings/multiple1/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple1/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00002.png b/tests/ragger/snapshots/stax/test_settings/multiple1/00002.png new file mode 100644 index 0000000000..d82692eefc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple1/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00003.png b/tests/ragger/snapshots/stax/test_settings/multiple1/00003.png new file mode 100644 index 0000000000..63fa5b49cd Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple1/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00004.png b/tests/ragger/snapshots/stax/test_settings/multiple1/00004.png new file mode 100644 index 0000000000..440d5e48cc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple1/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00005.png b/tests/ragger/snapshots/stax/test_settings/multiple1/00005.png new file mode 100644 index 0000000000..8d8f509706 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple1/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00006.png b/tests/ragger/snapshots/stax/test_settings/multiple1/00006.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple1/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple2/00000.png b/tests/ragger/snapshots/stax/test_settings/multiple2/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple2/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple2/00001.png b/tests/ragger/snapshots/stax/test_settings/multiple2/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple2/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple2/00002.png b/tests/ragger/snapshots/stax/test_settings/multiple2/00002.png new file mode 100644 index 0000000000..d82692eefc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple2/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple2/00003.png b/tests/ragger/snapshots/stax/test_settings/multiple2/00003.png new file mode 100644 index 0000000000..63fa5b49cd Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple2/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple2/00004.png b/tests/ragger/snapshots/stax/test_settings/multiple2/00004.png new file mode 100644 index 0000000000..3bd5f5f1cc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple2/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple2/00005.png b/tests/ragger/snapshots/stax/test_settings/multiple2/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple2/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple3/00000.png b/tests/ragger/snapshots/stax/test_settings/multiple3/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple3/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple3/00001.png b/tests/ragger/snapshots/stax/test_settings/multiple3/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple3/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple3/00002.png b/tests/ragger/snapshots/stax/test_settings/multiple3/00002.png new file mode 100644 index 0000000000..acf8d08f50 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple3/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple3/00003.png b/tests/ragger/snapshots/stax/test_settings/multiple3/00003.png new file mode 100644 index 0000000000..66172d3a40 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple3/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple3/00004.png b/tests/ragger/snapshots/stax/test_settings/multiple3/00004.png new file mode 100644 index 0000000000..124c1a4cda Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple3/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple3/00005.png b/tests/ragger/snapshots/stax/test_settings/multiple3/00005.png new file mode 100644 index 0000000000..a4a474c79b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple3/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple3/00006.png b/tests/ragger/snapshots/stax/test_settings/multiple3/00006.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/multiple3/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/nonce/00000.png b/tests/ragger/snapshots/stax/test_settings/nonce/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/nonce/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/nonce/00001.png b/tests/ragger/snapshots/stax/test_settings/nonce/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/nonce/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/nonce/00002.png b/tests/ragger/snapshots/stax/test_settings/nonce/00002.png new file mode 100644 index 0000000000..63fa5b49cd Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/nonce/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/nonce/00003.png b/tests/ragger/snapshots/stax/test_settings/nonce/00003.png new file mode 100644 index 0000000000..65f22d8229 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/nonce/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/nonce/00004.png b/tests/ragger/snapshots/stax/test_settings/nonce/00004.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/nonce/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/trusted_name/00000.png b/tests/ragger/snapshots/stax/test_settings/trusted_name/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/trusted_name/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/trusted_name/00001.png b/tests/ragger/snapshots/stax/test_settings/trusted_name/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/trusted_name/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/trusted_name/00002.png b/tests/ragger/snapshots/stax/test_settings/trusted_name/00002.png new file mode 100644 index 0000000000..63fa5b49cd Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/trusted_name/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/trusted_name/00003.png b/tests/ragger/snapshots/stax/test_settings/trusted_name/00003.png new file mode 100644 index 0000000000..579c48bcea Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/trusted_name/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/trusted_name/00004.png b/tests/ragger/snapshots/stax/test_settings/trusted_name/00004.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/trusted_name/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/web3_check/00000.png b/tests/ragger/snapshots/stax/test_settings/web3_check/00000.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/web3_check/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/web3_check/00001.png b/tests/ragger/snapshots/stax/test_settings/web3_check/00001.png new file mode 100644 index 0000000000..81eeba687c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/web3_check/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/web3_check/00002.png b/tests/ragger/snapshots/stax/test_settings/web3_check/00002.png new file mode 100644 index 0000000000..acf8d08f50 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/web3_check/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/web3_check/00003.png b/tests/ragger/snapshots/stax/test_settings/web3_check/00003.png new file mode 100644 index 0000000000..66172d3a40 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/web3_check/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/web3_check/00004.png b/tests/ragger/snapshots/stax/test_settings/web3_check/00004.png new file mode 100644 index 0000000000..124c1a4cda Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/web3_check/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/web3_check/00005.png b/tests/ragger/snapshots/stax/test_settings/web3_check/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_settings/web3_check/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_legacy_chainid/00000.png b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_chainid/00000.png rename to tests/ragger/snapshots/stax/test_sign_legacy_chainid/00000.png diff --git a/tests/ragger/snapshots/stax/test_legacy_chainid/00001.png b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_chainid/00001.png rename to tests/ragger/snapshots/stax/test_sign_legacy_chainid/00001.png diff --git a/tests/ragger/snapshots/stax/test_legacy_chainid/00002.png b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_chainid/00002.png rename to tests/ragger/snapshots/stax/test_sign_legacy_chainid/00002.png diff --git a/tests/ragger/snapshots/stax/test_legacy_chainid/00003.png b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_chainid/00003.png rename to tests/ragger/snapshots/stax/test_sign_legacy_chainid/00003.png diff --git a/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00004.png b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00005.png b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_sign_legacy_chainid/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_legacy_send_bsc/00000.png b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00000.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_send_bsc/00000.png rename to tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00000.png diff --git a/tests/ragger/snapshots/stax/test_legacy_send_bsc/00001.png b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00001.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_send_bsc/00001.png rename to tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00001.png diff --git a/tests/ragger/snapshots/stax/test_legacy_send_bsc/00002.png b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00002.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_send_bsc/00002.png rename to tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00002.png diff --git a/tests/ragger/snapshots/stax/test_legacy_send_bsc/00003.png b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00003.png similarity index 100% rename from tests/ragger/snapshots/stax/test_legacy_send_bsc/00003.png rename to tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00003.png diff --git a/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00004.png b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00005.png b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_sign_legacy_send_bsc/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_sign_parameter_selector/00006.png b/tests/ragger/snapshots/stax/test_sign_parameter_selector/00006.png index 0463721b10..e7a78b5be3 100644 Binary files a/tests/ragger/snapshots/stax/test_sign_parameter_selector/00006.png and b/tests/ragger/snapshots/stax/test_sign_parameter_selector/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_sign_parameter_selector/00007.png b/tests/ragger/snapshots/stax/test_sign_parameter_selector/00007.png index e993bf9987..a9cb3a2f07 100644 Binary files a/tests/ragger/snapshots/stax/test_sign_parameter_selector/00007.png and b/tests/ragger/snapshots/stax/test_sign_parameter_selector/00007.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00000.png new file mode 100644 index 0000000000..d0fb462776 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00001.png new file mode 100644 index 0000000000..1898206ed9 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00002.png new file mode 100644 index 0000000000..fcccc77dfe Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00003.png new file mode 100644 index 0000000000..3c89d74c4c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/warning/00000.png new file mode 100644 index 0000000000..e7a78b5be3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_benign/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00000.png new file mode 100644 index 0000000000..7b2f9f0e49 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00001.png new file mode 100644 index 0000000000..1898206ed9 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00002.png new file mode 100644 index 0000000000..fcccc77dfe Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00003.png new file mode 100644 index 0000000000..3c89d74c4c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/warning/00000.png new file mode 100644 index 0000000000..e7a78b5be3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_issue/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00000.png new file mode 100644 index 0000000000..a1a428d8e7 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00001.png new file mode 100644 index 0000000000..1898206ed9 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00002.png new file mode 100644 index 0000000000..fcccc77dfe Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00003.png new file mode 100644 index 0000000000..8bd3372f92 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/warning/00000.png new file mode 100644 index 0000000000..f6af04db0d Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_threat/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00000.png new file mode 100644 index 0000000000..65fa242fc0 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00001.png new file mode 100644 index 0000000000..1898206ed9 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00002.png new file mode 100644 index 0000000000..fcccc77dfe Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00003.png new file mode 100644 index 0000000000..3c89d74c4c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/warning/00000.png new file mode 100644 index 0000000000..4383643d74 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_blind_sign_warning/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00000.png new file mode 100644 index 0000000000..afb12296f8 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00001.png new file mode 100644 index 0000000000..06322edcec Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00002.png new file mode 100644 index 0000000000..e8aff8d1d9 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00003.png new file mode 100644 index 0000000000..cfee3aec2b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00004.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/warning/00000.png new file mode 100644 index 0000000000..5b9d527752 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00000.png new file mode 100644 index 0000000000..afb12296f8 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00001.png new file mode 100644 index 0000000000..630570e914 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00002.png new file mode 100644 index 0000000000..2051095282 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00003.png new file mode 100644 index 0000000000..fecace786a Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/warning/00000.png new file mode 100644 index 0000000000..5b9d527752 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip191_issue/warning/00000.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 new file mode 100644 index 0000000000..f6af04db0d Binary files /dev/null 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 new file mode 100644 index 0000000000..99aeb4ad94 Binary files /dev/null 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 new file mode 100644 index 0000000000..efce2dfe66 Binary files /dev/null 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 new file mode 100644 index 0000000000..6de7d8741c Binary files /dev/null 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 new file mode 100644 index 0000000000..cfee3aec2b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00000.png new file mode 100644 index 0000000000..4ea57a312e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00001.png new file mode 100644 index 0000000000..91237f1b84 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00002.png new file mode 100644 index 0000000000..e59f27d25f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00003.png new file mode 100644 index 0000000000..7d12ffb070 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00004.png new file mode 100644 index 0000000000..5126c73d6f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00005.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00006.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00006.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_gcs/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/warning/00000.png new file mode 100644 index 0000000000..4383643d74 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_gcs/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00000.png new file mode 100644 index 0000000000..b7ec531273 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00001.png new file mode 100644 index 0000000000..72ce397e6f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00002.png new file mode 100644 index 0000000000..ffdaeec4c8 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00003.png new file mode 100644 index 0000000000..955b4e51cc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png new file mode 100644 index 0000000000..4383643d74 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00000.png new file mode 100644 index 0000000000..6e1eaf156b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00001.png new file mode 100644 index 0000000000..666f5d5475 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00002.png new file mode 100644 index 0000000000..524435e29b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00003.png new file mode 100644 index 0000000000..9501e5bd98 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_no_simu/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_opt_in/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_opt_in/00000.png new file mode 100644 index 0000000000..acf8d08f50 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_opt_in/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_opt_in/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_opt_in/00001.png new file mode 100644 index 0000000000..66172d3a40 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_opt_in/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00000.png new file mode 100644 index 0000000000..93bbead4b8 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00001.png new file mode 100644 index 0000000000..666f5d5475 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00002.png new file mode 100644 index 0000000000..524435e29b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00003.png new file mode 100644 index 0000000000..0ad0d6a489 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_benign/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00000.png new file mode 100644 index 0000000000..6e1eaf156b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00001.png new file mode 100644 index 0000000000..666f5d5475 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00002.png new file mode 100644 index 0000000000..524435e29b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00003.png new file mode 100644 index 0000000000..9501e5bd98 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_issue/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00000.png new file mode 100644 index 0000000000..59a3a79777 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00001.png new file mode 100644 index 0000000000..666f5d5475 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00002.png new file mode 100644 index 0000000000..524435e29b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00003.png new file mode 100644 index 0000000000..0f01ce84ac Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00006.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00006.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/warning/00000.png new file mode 100644 index 0000000000..f6af04db0d Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00000.png new file mode 100644 index 0000000000..4e71f7fb45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00001.png new file mode 100644 index 0000000000..666f5d5475 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00002.png new file mode 100644 index 0000000000..524435e29b Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00003.png new file mode 100644 index 0000000000..ec775f43b5 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00004.png new file mode 100644 index 0000000000..392165d4fc Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00005.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00005.png new file mode 100644 index 0000000000..339db1b45c Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/warning/00000.png new file mode 100644 index 0000000000..4383643d74 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_sign_warning/warning/00000.png differ diff --git a/tests/ragger/test_blind_sign.py b/tests/ragger/test_blind_sign.py index acc85fec21..511e87db45 100644 --- a/tests/ragger/test_blind_sign.py +++ b/tests/ragger/test_blind_sign.py @@ -9,6 +9,7 @@ from ragger.backend import BackendInterface from ragger.firmware import Firmware from ragger.navigator import Navigator, NavInsID +from ragger.navigator.navigation_scenario import NavigateWithScenario from ragger.error import ExceptionRAPDU from constants import ABIS_FOLDER @@ -17,6 +18,7 @@ from client.settings import SettingID, settings_toggle import client.response_parser as ResponseParser from client.utils import recover_transaction +from client.tx_simu import TxSimu BIP32_PATH = "m/44'/60'/0'/0/0" @@ -63,22 +65,34 @@ def common_tx_params(amount: float) -> dict: def test_blind_sign(firmware: Firmware, backend: BackendInterface, navigator: Navigator, + scenario_navigator: NavigateWithScenario, default_screenshot_path: Path, test_name: str, reject: bool, - amount: float): + amount: float, + simu_params: Optional[TxSimu] = None): global DEVICE_ADDR app_client = EthAppClient(backend) if reject and amount > 0.0: pytest.skip() + + tx_params = common_tx_params(amount) + + if not reject and simu_params is not None: + _, tx_hash = app_client.serialize_tx(tx_params) + simu_params.tx_hash = tx_hash + simu_params.chain_id = tx_params["chainId"] + simu_params.from_addr = DEVICE_ADDR + response = app_client.provide_tx_simulation(simu_params) + assert response.status == StatusWord.OK + settings_toggle(firmware, navigator, [SettingID.BLIND_SIGNING]) if DEVICE_ADDR is None: with app_client.get_public_addr(bip32_path=BIP32_PATH, display=False): pass _, DEVICE_ADDR, _ = ResponseParser.pk_addr(app_client.response().data) - tx_params = common_tx_params(amount) try: with app_client.sign(BIP32_PATH, tx_params): if reject: @@ -87,57 +101,25 @@ def test_blind_sign(firmware: Firmware, if amount > 0.0: test_name += "_nonzero" - moves = [] if firmware.is_nano: - # blind signing warning - moves += [NavInsID.RIGHT_CLICK] - - # review - moves += [NavInsID.RIGHT_CLICK] - - # tx hash - if firmware == Firmware.NANOS: - moves += [NavInsID.RIGHT_CLICK] * 4 - else: - moves += [NavInsID.RIGHT_CLICK] * 2 - - # from - if firmware == Firmware.NANOS: - moves += [NavInsID.RIGHT_CLICK] * 3 - else: - moves += [NavInsID.RIGHT_CLICK] - - # amount - if amount > 0.0: - moves += [NavInsID.RIGHT_CLICK] - - # to - if firmware == Firmware.NANOS: - moves += [NavInsID.RIGHT_CLICK] * 3 - else: - moves += [NavInsID.RIGHT_CLICK] - - # fees - moves += [NavInsID.RIGHT_CLICK] - - if reject: - moves += [NavInsID.RIGHT_CLICK] - - moves += [NavInsID.BOTH_CLICK] + end_text = "^Accept risk" + moves = [NavInsID.RIGHT_CLICK] else: - moves += [NavInsID.USE_CASE_CHOICE_REJECT] + end_text = "^Hold to sign$" + moves = [NavInsID.USE_CASE_CHOICE_REJECT] - moves += [NavInsID.SWIPE_CENTER_TO_LEFT] * 3 + if not firmware.is_nano: + # Warning Screen + navigator.navigate_and_compare(default_screenshot_path, + f"{test_name}/warning", + moves, + screen_change_after_last_instruction=False) - if not reject: - moves += [NavInsID.USE_CASE_REVIEW_CONFIRM] - else: - moves += [NavInsID.USE_CASE_REVIEW_REJECT] - moves += [NavInsID.USE_CASE_CHOICE_CONFIRM] + if reject: + scenario_navigator.review_reject(test_name=test_name) + else: + scenario_navigator.review_approve(test_name=test_name, custom_screen_text=end_text) - navigator.navigate_and_compare(default_screenshot_path, - test_name, - moves) except ExceptionRAPDU as e: assert reject assert e.status == StatusWord.CONDITION_NOT_SATISFIED diff --git a/tests/ragger/test_clone.py b/tests/ragger/test_clone.py index 4419227fbc..f3770bc090 100644 --- a/tests/ragger/test_clone.py +++ b/tests/ragger/test_clone.py @@ -1,3 +1,5 @@ +import pytest + from pathlib import Path from web3 import Web3 @@ -19,6 +21,7 @@ # Transfer on Clone app +@pytest.mark.needs_setup('lib_mode') def test_clone_thundercore(firmware: Firmware, backend: BackendInterface, navigator: Navigator, diff --git a/tests/ragger/test_configuration_cmd.py b/tests/ragger/test_configuration_cmd.py index 99e8760eee..f3003bde4c 100644 --- a/tests/ragger/test_configuration_cmd.py +++ b/tests/ragger/test_configuration_cmd.py @@ -1,49 +1,53 @@ from pathlib import Path from typing import List -import re +import pytest from ragger.backend import BackendInterface +from ragger.firmware import Firmware +from ragger.navigator import Navigator from ragger.utils.misc import get_current_app_name_and_version - -def test_check_version(backend: BackendInterface): +from client.settings import SettingID, get_settings_moves + + +@pytest.mark.parametrize( + "name, setting", + [ + ("web3_check", [SettingID.WEB3_CHECK]), + ("blind_sign", [SettingID.BLIND_SIGNING]), + ("trusted_name", [SettingID.VERBOSE_ENS]), + ("nonce", [SettingID.NONCE]), + ("eip712_token", [SettingID.VERBOSE_EIP712]), + ("debug_token", [SettingID.DEBUG_DATA]), + ("multiple1", [SettingID.BLIND_SIGNING, SettingID.DEBUG_DATA]), + ("multiple2", [SettingID.BLIND_SIGNING, SettingID.VERBOSE_EIP712]), + ("multiple3", [SettingID.BLIND_SIGNING, SettingID.WEB3_CHECK]), + ] +) +def test_settings(firmware: Firmware, + navigator: Navigator, + test_name: str, + default_screenshot_path: Path, + name: str, + setting: List[SettingID]): + """Check the settings""" + + if firmware.is_nano: + pytest.skip("Skipping on Nano") + + moves = get_settings_moves(firmware, setting) + navigator.navigate_and_compare(default_screenshot_path, + f"{test_name}/{name}", + moves, screen_change_before_first_instruction=False) + + +def test_check_version(backend: BackendInterface, app_version: tuple[int, int, int]): """Check version and name""" # Send the APDU app_name, version = get_current_app_name_and_version(backend) print(f" Name: {app_name}") print(f" Version: {version}") - _verify_version(version.split("-")[0]) - - -def _verify_version(version: str) -> None: - """Verify the app version, based on defines in Makefile - - Args: - Version (str): Version to be checked - """ - - vers_dict = {} - vers_str = "" - lines = _read_makefile() - version_re = re.compile(r"^APPVERSION_(?P\w)\s?=\s?(?P\d*)", re.I) - for line in lines: - info = version_re.match(line) - if info: - dinfo = info.groupdict() - vers_dict[dinfo["part"]] = dinfo["val"] - try: - vers_str = f"{vers_dict['M']}.{vers_dict['N']}.{vers_dict['P']}" - except KeyError: - pass - assert version == vers_str - - -def _read_makefile() -> List[str]: - """Read lines from the parent Makefile """ - - parent = Path(__file__).parent.parent.parent.resolve() - makefile = f"{parent}/Makefile" - with open(makefile, "r", encoding="utf-8") as f_p: - lines = f_p.readlines() - return lines + print(f" app_version: {app_version}") + vers_str = ".".join(map(str, app_version)) + assert version.split("-")[0] == vers_str diff --git a/tests/ragger/test_eip191.py b/tests/ragger/test_eip191.py index 1edd22e7c4..cb9c6818ec 100644 --- a/tests/ragger/test_eip191.py +++ b/tests/ragger/test_eip191.py @@ -1,22 +1,38 @@ +from pathlib import Path +from typing import Optional import pytest +from Crypto.Hash import keccak from ragger.error import ExceptionRAPDU from ragger.backend import BackendInterface from ragger.firmware import Firmware +from ragger.navigator import Navigator, NavInsID from ragger.navigator.navigation_scenario import NavigateWithScenario from client.client import EthAppClient, StatusWord import client.response_parser as ResponseParser from client.utils import recover_message +from client.tx_simu import TxSimu BIP32_PATH = "m/44'/60'/0'/0/0" +def handle_simulation(app_client: EthAppClient, msg: str, simu_params: TxSimu) -> None: + msg_to_sign = b"\x19Ethereum Signed Message:\n" + str(len(msg)).encode("utf-8") + msg.encode("utf-8") + if not simu_params.tx_hash: + simu_params.tx_hash = keccak.new(digest_bits=256, data=msg_to_sign).digest() + response = app_client.provide_tx_simulation(simu_params) + assert response.status == StatusWord.OK + + def common(backend: BackendInterface, + navigator: Navigator, scenario: NavigateWithScenario, + default_screenshot_path: Path, test_name: str, - msg: str): + msg: str, + simu_params: Optional[TxSimu] = None): app_client = EthAppClient(backend) @@ -24,34 +40,65 @@ def common(backend: BackendInterface, pass _, DEVICE_ADDR, _ = ResponseParser.pk_addr(app_client.response().data) - with app_client.personal_sign(BIP32_PATH, msg.encode('utf-8')): - scenario.review_approve(test_name=test_name, custom_screen_text="Sign") + if simu_params: + simu_params.from_addr = DEVICE_ADDR + handle_simulation(app_client, msg, simu_params) + + try: + with app_client.personal_sign(BIP32_PATH, msg.encode('utf-8')): + if simu_params is not None: + navigator.navigate_and_compare(default_screenshot_path, + f"{test_name}/warning", + [NavInsID.USE_CASE_CHOICE_REJECT], + screen_change_after_last_instruction=False) + + if simu_params and "tx_hash" in simu_params: + navigator.navigate_until_text_and_compare(NavInsID.SWIPE_CENTER_TO_LEFT, + [NavInsID.USE_CASE_CHOICE_CONFIRM], + "Transaction Check", + default_screenshot_path, + test_name) + else: + scenario.review_approve(test_name=test_name, custom_screen_text=r"(Sign|Accept (risk|threat))") + + except ExceptionRAPDU as err: + if simu_params and "tx_hash" in simu_params: + assert err.status == StatusWord.CONDITION_NOT_SATISFIED + else: + assert False, f"Unexpected exception: {err}" - # verify signature - vrs = ResponseParser.signature(app_client.response().data) - addr = recover_message(msg.encode('utf-8'), vrs) - assert addr == DEVICE_ADDR + if simu_params is None or "tx_hash" not in simu_params: + # verify signature + vrs = ResponseParser.signature(app_client.response().data) + addr = recover_message(msg.encode('utf-8'), vrs) + assert addr == DEVICE_ADDR def test_personal_sign_metamask(backend: BackendInterface, + navigator: Navigator, scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, test_name: str): msg = "Example `personal_sign` message" - common(backend, scenario_navigator, test_name, msg) + common(backend, navigator, scenario_navigator, default_screenshot_path, test_name, msg) def test_personal_sign_non_ascii(backend: BackendInterface, + navigator: Navigator, scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, test_name: str): msg = "0x9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658" - common(backend, scenario_navigator, test_name, msg) + common(backend, navigator, scenario_navigator, default_screenshot_path, test_name, msg) def test_personal_sign_opensea(firmware: Firmware, backend: BackendInterface, + navigator: Navigator, scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, test_name: str): if firmware == Firmware.NANOS: @@ -62,7 +109,7 @@ def test_personal_sign_opensea(firmware: Firmware, msg += "This request will not trigger a blockchain transaction or cost any gas fees.\n\n" msg += "Your authentication status will reset after 24 hours.\n\n" msg += "Wallet address:\n0x9858effd232b4033e47d90003d41ec34ecaeda94\n\nNonce:\n2b02c8a0-f74f-4554-9821-a28054dc9121" - common(backend, scenario_navigator, test_name, msg) + common(backend, navigator, scenario_navigator, default_screenshot_path, test_name, msg) def test_personal_sign_reject(firmware: Firmware, diff --git a/tests/ragger/test_eip712.py b/tests/ragger/test_eip712.py index 6904709cb2..b2b17bcd1d 100644 --- a/tests/ragger/test_eip712.py +++ b/tests/ragger/test_eip712.py @@ -11,6 +11,7 @@ from ragger.backend import BackendInterface from ragger.firmware import Firmware +from ragger.firmware.touch.positions import POSITIONS from ragger.navigator import Navigator, NavInsID, NavIns from ragger.error import ExceptionRAPDU @@ -19,13 +20,15 @@ from client.client import EthAppClient, StatusWord, TrustedNameType, TrustedNameSource from client.eip712 import InputData from client.settings import SettingID, settings_toggle +from client.tx_simu import TxSimu +from client.proxy_info import ProxyInfo BIP32_PATH = "m/44'/60'/0'/0/0" autonext_idx: int snapshots_dirname: Optional[str] = None WALLET_ADDR: Optional[bytes] = None -unfiltered_flow: bool = False +validate_warning: bool = False skip_flow: bool = False @@ -42,12 +45,12 @@ def input_files() -> list[str]: @pytest.fixture(name="input_file", params=input_files()) -def input_file_fixture(request) -> str: +def input_file_fixture(request) -> Path: return Path(request.param) -@pytest.fixture(name="verbose", params=[True, False]) -def verbose_fixture(request) -> bool: +@pytest.fixture(name="verbose_raw", params=[True, False]) +def verbose_raw_fixture(request) -> bool: return request.param @@ -67,13 +70,29 @@ def get_wallet_addr(client: EthAppClient) -> bytes: return WALLET_ADDR -def test_eip712_v0(firmware: Firmware, backend: BackendInterface, navigator: Navigator): +def test_eip712_v0(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + simu_params: Optional[TxSimu] = None): + global validate_warning + app_client = EthAppClient(backend) + DEVICE_ADDR = get_wallet_addr(app_client) + settings_toggle(firmware, 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 + simu_params.from_addr = DEVICE_ADDR + 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 + with app_client.eip712_sign_legacy(BIP32_PATH, smsg.header, smsg.body): moves = [] if firmware.is_nano: @@ -90,9 +109,7 @@ def test_eip712_v0(firmware: Firmware, backend: BackendInterface, navigator: Nav navigator.navigate(moves) vrs = ResponseParser.signature(app_client.response().data) - recovered_addr = recover_message(data, vrs) - - assert recovered_addr == get_wallet_addr(app_client) + assert DEVICE_ADDR == recover_message(data, vrs) def autonext(firmware: Firmware, navigator: Navigator, default_screenshot_path: Path): @@ -102,18 +119,14 @@ def autonext(firmware: Firmware, navigator: Navigator, default_screenshot_path: if firmware.is_nano: moves = [NavInsID.RIGHT_CLICK] else: - if autonext_idx == 0 and unfiltered_flow: + 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 - if firmware == Firmware.STAX: - skip_btn_pos = (355, 44) - else: # FLEX - skip_btn_pos = (420, 49) moves = [ # Ragger does not handle the skip button - NavIns(NavInsID.TOUCH, skip_btn_pos), + NavIns(NavInsID.TOUCH, POSITIONS["RightHeader"][firmware]), NavInsID.USE_CASE_CHOICE_CONFIRM, ] else: @@ -141,7 +154,7 @@ def eip712_new_common(firmware: Firmware, verbose: bool, golden_run: bool): global autonext_idx - global unfiltered_flow + global validate_warning global skip_flow global snapshots_dirname @@ -180,33 +193,36 @@ def eip712_new_common(firmware: Firmware, screen_change_before_first_instruction=False, screen_change_after_last_instruction=False) # reset values - unfiltered_flow = False + validate_warning = False skip_flow = False snapshots_dirname = None return ResponseParser.signature(app_client.response().data) +def get_filter_file_from_data_file(data_file: Path) -> Path: + test_path = f"{data_file.parent}/{'-'.join(data_file.stem.split('-')[:-1])}" + return Path(f"{test_path}-filter.json") + + def test_eip712_new(firmware: Firmware, backend: BackendInterface, navigator: Navigator, default_screenshot_path: Path, input_file: Path, - verbose: bool, + verbose_raw: bool, filtering: bool): - global unfiltered_flow + global validate_warning settings_to_toggle: list[SettingID] = [] app_client = EthAppClient(backend) if firmware == Firmware.NANOS: pytest.skip("Not supported on LNS") - test_path = f"{input_file.parent}/{'-'.join(input_file.stem.split('-')[:-1])}" - filters = None if filtering: try: - filterfile = Path(f"{test_path}-filter.json") + filterfile = get_filter_file_from_data_file(input_file) with open(filterfile, encoding="utf-8") as f: filters = json.load(f) except (IOError, json.decoder.JSONDecodeError) as e: @@ -214,11 +230,11 @@ def test_eip712_new(firmware: Firmware, else: settings_to_toggle.append(SettingID.BLIND_SIGNING) - if verbose: + if verbose_raw: settings_to_toggle.append(SettingID.VERBOSE_EIP712) - if not filters or verbose: - unfiltered_flow = True + if not filters or verbose_raw: + validate_warning = True if len(settings_to_toggle) > 0: settings_toggle(firmware, navigator, settings_to_toggle) @@ -231,7 +247,7 @@ def test_eip712_new(firmware: Firmware, app_client, data, filters, - verbose, + verbose_raw, False) recovered_addr = recover_message(data, vrs) @@ -491,8 +507,10 @@ def test_eip712_filtering_empty_array(firmware: Firmware, navigator: Navigator, default_screenshot_path: Path, test_name: str, - golden_run: bool): + golden_run: bool, + simu_params: Optional[TxSimu] = None): global snapshots_dirname + global validate_warning app_client = EthAppClient(backend) if firmware == Firmware.NANOS: @@ -563,6 +581,15 @@ def test_eip712_filtering_empty_array(firmware: Firmware, }, } } + + if simu_params is not None: + validate_warning = True + 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(firmware, navigator, default_screenshot_path, @@ -613,7 +640,7 @@ def test_eip712_advanced_missing_token(firmware: Firmware, golden_run: bool): global snapshots_dirname - test_name += "-%s-%s" % (len(tokens[0]) == 0, len(tokens[1]) == 0) + test_name += f"-{len(tokens[0]) == 0}-{len(tokens[1]) == 0}" snapshots_dirname = test_name app_client = EthAppClient(backend) @@ -721,9 +748,9 @@ def test_eip712_advanced_trusted_name(firmware: Firmware, golden_run: bool): global snapshots_dirname - test_name += "_%s_with" % (str(trusted_name[0]).split(".")[-1].lower()) + test_name += f"_{trusted_name[0].name.lower()}_with" for t in filt_tn_types: - test_name += "_%s" % (str(t).split(".")[-1].lower()) + test_name += f"_{t.name.lower()}" snapshots_dirname = test_name app_client = EthAppClient(backend) @@ -822,16 +849,15 @@ def test_eip712_skip(firmware: Firmware, backend: BackendInterface, navigator: Navigator, default_screenshot_path: Path, - test_name: str, golden_run: bool): - global unfiltered_flow + global validate_warning global skip_flow app_client = EthAppClient(backend) if firmware.is_nano: pytest.skip("Not supported on Nano devices") - unfiltered_flow = True + validate_warning = True skip_flow = True settings_toggle(firmware, navigator, [SettingID.BLIND_SIGNING]) with open(input_files()[0], encoding="utf-8") as file: @@ -848,3 +874,43 @@ def test_eip712_skip(firmware: Firmware, # verify signature addr = recover_message(data, vrs) assert addr == get_wallet_addr(app_client) + + +def test_eip712_proxy(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + default_screenshot_path: Path): + app_client = EthAppClient(backend) + if firmware == Firmware.NANOS: + pytest.skip("Not supported on LNS") + + input_file = input_files()[0] + with open(input_file) as file: + data = json.load(file) + with open(get_filter_file_from_data_file(Path(input_file))) as file: + filters = json.load(file) + # change its name & set a different address than the one in verifyingContract + filters["name"] = "Proxy test" + filters["address"] = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + proxy_info = ProxyInfo( + ResponseParser.challenge(app_client.get_challenge().data), + bytes.fromhex(filters["address"][2:]), + int(data["domain"]["chainId"]), + bytes.fromhex(data["domain"]["verifyingContract"][2:]), + ) + + app_client.provide_proxy_info(proxy_info.serialize()) + + vrs = eip712_new_common(firmware, + navigator, + default_screenshot_path, + app_client, + data, + filters, + False, + False) + + # verify signature + addr = recover_message(data, vrs) + assert addr == get_wallet_addr(app_client) diff --git a/tests/ragger/test_gcs.py b/tests/ragger/test_gcs.py index a05c0c0667..92cda3b7ae 100644 --- a/tests/ragger/test_gcs.py +++ b/tests/ragger/test_gcs.py @@ -1,27 +1,35 @@ +from pathlib import Path +from typing import Optional import struct import json import hashlib +import pytest +from web3 import Web3 from ragger.backend import BackendInterface from ragger.firmware import Firmware -from ragger.navigator import Navigator +from ragger.navigator import Navigator, NavInsID from ragger.navigator.navigation_scenario import NavigateWithScenario -import pytest -from web3 import Web3 - -import client.response_parser as ResponseParser -from client.client import EthAppClient, SignMode, TrustedNameType, TrustedNameSource -from client.utils import get_selector_from_data -from client.gcs import * from constants import ABIS_FOLDER - -def test_nft(firmware: Firmware, - backend: BackendInterface, - scenario_navigator: NavigateWithScenario, - test_name: str): +import client.response_parser as ResponseParser +from client.client import EthAppClient, SignMode, TrustedNameType, TrustedNameSource, StatusWord +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 +) +from client.tx_simu import TxSimu +from client.proxy_info import ProxyInfo + + +def test_gcs_nft(firmware: Firmware, + backend: BackendInterface, + scenario_navigator: NavigateWithScenario, + test_name: str): app_client = EthAppClient(backend) if firmware == Firmware.NANOS: @@ -32,10 +40,12 @@ def test_nft(firmware: Firmware, abi=json.load(file), address=None ) - recipient_addr = bytes.fromhex("1111111111111111111111111111111111111111") + with app_client.get_public_addr(bip32_path="m/44'/60'/0'/0/0", display=False): + pass + _, device_addr, _ = ResponseParser.pk_addr(app_client.response().data) data = contract.encode_abi("safeBatchTransferFrom", [ - bytes.fromhex("Dad77910DbDFdE764fC21FCD4E74D71bBACA6D8D"), - recipient_addr, + bytes.fromhex("1111111111111111111111111111111111111111"), + bytes.fromhex("d8da6bf26964af9d7eed9e03e53415d37aa96045"), [ 0xff, 0xffff, @@ -60,15 +70,15 @@ def test_nft(firmware: Firmware, "data": data, "chainId": 1 } - with app_client.sign("m/44'/60'/0'/0/0", tx_params, SignMode.STORE): + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): pass fields = [ Field( 1, "From", - ParamType.RAW, - ParamRaw( + ParamType.TRUSTED_NAME, + ParamTrustedName( 1, Value( 1, @@ -80,14 +90,27 @@ def test_nft(firmware: Firmware, PathLeaf(PathLeafType.STATIC), ] ), - ) + ), + [ + TrustedNameType.ACCOUNT, + ], + [ + TrustedNameSource.UD, + TrustedNameSource.ENS, + TrustedNameSource.FN, + ], + [ + bytes.fromhex("0000000000000000000000000000000000000000"), + bytes.fromhex("1111111111111111111111111111111111111111"), + bytes.fromhex("2222222222222222222222222222222222222222"), + ], ) ), Field( 1, "To", - ParamType.TRUSTED_NAME, - ParamTrustedName( + ParamType.RAW, + ParamRaw( 1, Value( 1, @@ -99,15 +122,7 @@ def test_nft(firmware: Firmware, PathLeaf(PathLeafType.STATIC), ] ), - ), - [ - TrustedNameType.ACCOUNT, - ], - [ - TrustedNameSource.UD, - TrustedNameSource.ENS, - TrustedNameSource.FN, - ], + ) ) ), Field( @@ -197,7 +212,7 @@ def test_nft(firmware: Firmware, app_client.provide_transaction_info(tx_info.serialize()) challenge = ResponseParser.challenge(app_client.get_challenge().data) - app_client.provide_trusted_name_v2(recipient_addr, + app_client.provide_trusted_name_v2(device_addr, "gerard.eth", TrustedNameType.ACCOUNT, TrustedNameSource.ENS, @@ -213,10 +228,13 @@ def test_nft(firmware: Firmware, scenario_navigator.review_approve(test_name=test_name, custom_screen_text="Sign transaction") -def test_poap(firmware: Firmware, - backend: BackendInterface, - scenario_navigator: NavigateWithScenario, - test_name: str): +def test_gcs_poap(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path, + simu_params: Optional[TxSimu] = None): app_client = EthAppClient(backend) if firmware == Firmware.NANOS: @@ -227,6 +245,7 @@ def test_poap(firmware: Firmware, abi=json.load(file), address=None ) + # pylint: disable=line-too-long data = contract.encode_abi("mintToken", [ 175676, 7163978, @@ -244,7 +263,16 @@ def test_poap(firmware: Firmware, "data": data, "chainId": 1 } - with app_client.sign("m/44'/60'/0'/0/0", tx_params, SignMode.STORE): + # pylint: enable=line-too-long + + if simu_params is not None: + _, tx_hash = app_client.serialize_tx(tx_params) + simu_params.tx_hash = tx_hash + simu_params.chain_id = tx_params["chainId"] + response = app_client.provide_tx_simulation(simu_params) + assert response.status == StatusWord.OK + + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): pass fields = [ @@ -376,13 +404,20 @@ def test_poap(firmware: Firmware, app_client.send_raw(0xe0, 0x28, 0x01, 0x00, struct.pack(">H", len(payload)) + payload) with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): - scenario_navigator.review_approve(test_name=test_name, custom_screen_text="Sign transaction") + if simu_params is not None: + navigator.navigate_and_compare(default_screenshot_path, + f"{test_name}/warning", + [NavInsID.USE_CASE_CHOICE_REJECT], + screen_change_after_last_instruction=False) + + scenario_navigator.review_approve(test_name=test_name, + custom_screen_text=r"(Sign transaction|Accept (risk|threat))") -def test_1inch(firmware: Firmware, - backend: BackendInterface, - scenario_navigator: NavigateWithScenario, - test_name: str): +def test_gcs_1inch(firmware: Firmware, + backend: BackendInterface, + scenario_navigator: NavigateWithScenario, + test_name: str): app_client = EthAppClient(backend) if firmware == Firmware.NANOS: @@ -416,7 +451,7 @@ def test_1inch(firmware: Firmware, "data": data, "chainId": 1 } - with app_client.sign("m/44'/60'/0'/0/0", tx_params, SignMode.STORE): + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): pass fields = [ @@ -542,3 +577,240 @@ def test_1inch(firmware: Firmware, with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): scenario_navigator.review_approve(test_name=test_name, custom_screen_text="Sign transaction") + + +def test_gcs_proxy(firmware: Firmware, + backend: BackendInterface, + scenario_navigator: NavigateWithScenario, + test_name: str): + app_client = EthAppClient(backend) + + if firmware == Firmware.NANOS: + pytest.skip("Not supported on LNS") + + new_owner = bytes.fromhex("2222222222222222222222222222222222222222") + + with open(f"{ABIS_FOLDER}/proxy_implem.abi.json") as file: + contract = Web3().eth.contract( + abi=json.load(file), + address=None + ) + data = contract.encode_abi("transferOwnership", [ + new_owner, + ]) + tx_params = { + "nonce": 1, + "maxFeePerGas": Web3.to_wei(100, "gwei"), + "maxPriorityFeePerGas": Web3.to_wei(10, "gwei"), + "gas": 230, + # address of the proxy contract + "to": bytes.fromhex("39053d51b77dc0d36036fc1fcc8cb819df8ef37a"), + "data": data, + "chainId": 1 + } + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): + pass + + fields = [ + Field( + 1, + "New owner", + ParamType.TRUSTED_NAME, + ParamTrustedName( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + [TrustedNameType.CONTRACT], + [TrustedNameSource.CAL], + ) + ), + ] + + # compute instructions hash + inst_hash = hashlib.sha3_256() + for field in fields: + inst_hash.update(field.serialize()) + + tx_info = TxInfo( + 1, + tx_params["chainId"], + # address of the implementation contract + bytes.fromhex("1784be6401339fc0fedf7e9379409f5c1bfe9dda"), + get_selector_from_data(tx_params["data"]), + inst_hash.digest(), + "transfer ownership", + creator_name="EigenLayer", + creator_legal_name="Eigen Labs", + creator_url="https://eigenlayer.xyz", + contract_name="Delegation Manager", + deploy_date=1711098731, + ) + + proxy_info = ProxyInfo( + ResponseParser.challenge(app_client.get_challenge().data), + tx_info.contract_addr, + tx_info.chain_id, + tx_params["to"], + tx_info.selector, + ) + + app_client.provide_proxy_info(proxy_info.serialize()) + + app_client.provide_transaction_info(tx_info.serialize()) + + # also test proxy trusted names + impl_contract = bytes.fromhex("1111111111111111111111111111111111111111") + proxy_info = ProxyInfo( + ResponseParser.challenge(app_client.get_challenge().data), + new_owner, + tx_info.chain_id, + impl_contract, + ) + + app_client.provide_proxy_info(proxy_info.serialize()) + + app_client.provide_trusted_name_v2(impl_contract, + "some contract", + TrustedNameType.CONTRACT, + TrustedNameSource.CAL, + tx_info.chain_id, + 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) + + with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): + scenario_navigator.review_approve(test_name=test_name, custom_screen_text="Sign transaction") + + +def test_gcs_4226(firmware: Firmware, + backend: BackendInterface, + scenario_navigator: NavigateWithScenario, + test_name: str): + app_client = EthAppClient(backend) + + if firmware == Firmware.NANOS: + pytest.skip("Not supported on LNS") + + with open(f"{ABIS_FOLDER}/rSWELL.abi.json") as file: + contract = Web3().eth.contract( + abi=json.load(file), + address=None + ) + data = contract.encode_abi("deposit", [ + Web3.to_wei(4.20, "ether"), + bytes.fromhex("Dad77910DbDFdE764fC21FCD4E74D71bBACA6D8D"), + ]) + tx_params = { + "nonce": 235, + "maxFeePerGas": Web3.to_wei(3, "gwei"), + "maxPriorityFeePerGas": Web3.to_wei(1, "gwei"), + "gas": 128872, + "to": bytes.fromhex("358d94b5b2F147D741088803d932Acb566acB7B6"), + "data": data, + "chainId": 1 + } + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): + pass + + swell_token_addr = bytes.fromhex("0a6e7ba5042b38349e437ec6db6214aec7b35676") + fields = [ + Field( + 1, + "Deposit asset", + ParamType.TOKEN_AMOUNT, + ParamTokenAmount( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + token=Value( + 1, + TypeFamily.ADDRESS, + constant=swell_token_addr, + ), + ) + ), + Field( + 1, + "Receive shares", + ParamType.TOKEN, + ParamToken( + 1, + Value( + 1, + TypeFamily.ADDRESS, + container_path=ContainerPath.TO, + ), + ) + ), + Field( + 1, + "Send shares to", + ParamType.RAW, + ParamToken( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(1), + 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(), + "deposit", + creator_name="Swell", + creator_legal_name="Swell Network", + creator_url="www.swellnetwork.io", + contract_name="rSWELL Token", + deploy_date=1726817291 + ) + + app_client.provide_transaction_info(tx_info.serialize()) + + app_client.provide_token_metadata("rSWELL", tx_params["to"], 18, 1) + 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) + + with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): + scenario_navigator.review_approve(test_name=test_name, custom_screen_text="Sign transaction") diff --git a/tests/ragger/test_get_address.py b/tests/ragger/test_get_address.py index e670295a2a..73a23e25d1 100644 --- a/tests/ragger/test_get_address.py +++ b/tests/ragger/test_get_address.py @@ -35,19 +35,23 @@ def chain_fixture(request) -> Optional[int]: ) def test_get_pk_rejected(backend: BackendInterface, scenario_navigator: NavigateWithScenario, - path, - suffix): + test_name: str, + path: str, + suffix: str): app_client = EthAppClient(backend) + test_name += f"_{suffix}" with pytest.raises(ExceptionRAPDU) as e: with app_client.get_public_addr(bip32_path=path): - scenario_navigator.address_review_reject(test_name=f"get_pk_rejected_{suffix}") + scenario_navigator.address_review_reject(test_name=test_name) assert e.value.status == StatusWord.CONDITION_NOT_SATISFIED -def test_get_pk(backend: BackendInterface, +def test_get_pk(firmware: Firmware, + backend: BackendInterface, scenario_navigator: NavigateWithScenario, + test_name: str, with_chaincode: bool, chain: Optional[int]): app_client = EthAppClient(backend) @@ -66,12 +70,15 @@ def test_get_pk(backend: BackendInterface, # pylint: enable=line-too-long else: name = "" + ticker = "" + icon = "" - if (app_client._firmware != Firmware.NANOS) and name: + if (firmware != Firmware.NANOS) and name: app_client.provide_network_information(name, ticker, chain, bytes.fromhex(icon)) + test_name += f"_{chain}" with app_client.get_public_addr(chaincode=with_chaincode, chain_id=chain): - scenario_navigator.address_review_approve(test_name=f"get_pk_{chain}") + scenario_navigator.address_review_approve(test_name=test_name) pk, _, chaincode = ResponseParser.pk_addr(app_client.response().data, with_chaincode) ref_pk, ref_chaincode = calculate_public_key_and_chaincode(curve=CurveChoice.Secp256k1, diff --git a/tests/ragger/test_nft.py b/tests/ragger/test_nft.py index d80f8a03a8..3988644188 100644 --- a/tests/ragger/test_nft.py +++ b/tests/ragger/test_nft.py @@ -1,3 +1,4 @@ +from pathlib import Path from typing import Callable, Optional, Any import json import pytest @@ -6,6 +7,7 @@ from ragger.error import ExceptionRAPDU from ragger.firmware import Firmware from ragger.backend import BackendInterface +from ragger.navigator import Navigator, NavInsID from ragger.navigator.navigation_scenario import NavigateWithScenario from constants import ABIS_FOLDER @@ -13,6 +15,7 @@ from client.client import EthAppClient, StatusWord import client.response_parser as ResponseParser from client.utils import get_selector_from_data, recover_transaction +from client.tx_simu import TxSimu BIP32_PATH = "m/44'/60'/0'/0/0" @@ -49,17 +52,39 @@ def __init__(self, fn_name: str, fn_args: list[Any]): def common_test_nft(firmware: Firmware, backend: BackendInterface, + navigator: Navigator, scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, + test_name: str, collec: NFTCollection, action: Action, reject: bool, - plugin_name: str): + plugin_name: str, + simu_params: Optional[TxSimu] = None): global DEVICE_ADDR app_client = EthAppClient(backend) if firmware == Firmware.NANOS: pytest.skip("Not supported on LNS") + data = collec.contract.encode_abi(action.fn_name, action.fn_args) + tx_params = { + "nonce": NONCE, + "gasPrice": Web3.to_wei(GAS_PRICE, "gwei"), + "gas": GAS_LIMIT, + "to": collec.addr, + "value": 0, + "chainId": collec.chain_id, + "data": data, + } + if not reject and simu_params is not None: + _, tx_hash = app_client.serialize_tx(tx_params) + simu_params.from_addr = DEVICE_ADDR + simu_params.tx_hash = tx_hash + simu_params.chain_id = tx_params["chainId"] + response = app_client.provide_tx_simulation(simu_params) + assert response.status == StatusWord.OK + if collec.chain_id == 5: name = "Goerli" ticker = "ETH" @@ -74,6 +99,8 @@ def common_test_nft(firmware: Firmware, # pylint: enable=line-too-long else: name = "" + ticker = "" + icon = "" if name: app_client.provide_network_information(name, ticker, collec.chain_id, bytes.fromhex(icon)) @@ -83,32 +110,28 @@ def common_test_nft(firmware: Firmware, pass _, DEVICE_ADDR, _ = ResponseParser.pk_addr(app_client.response().data) - data = collec.contract.encode_abi(action.fn_name, action.fn_args) app_client.set_plugin(plugin_name, collec.addr, get_selector_from_data(data), collec.chain_id) app_client.provide_nft_metadata(collec.name, collec.addr, collec.chain_id) - tx_params = { - "nonce": NONCE, - "gasPrice": Web3.to_wei(GAS_PRICE, "gwei"), - "gas": GAS_LIMIT, - "to": collec.addr, - "value": 0, - "chainId": collec.chain_id, - "data": data, - } + with app_client.sign(BIP32_PATH, tx_params): - test_name = f"{plugin_name.lower()}_{action.fn_name}_{str(collec.chain_id)}" + test_name += f"_{action.fn_name}_{str(collec.chain_id)}" if reject: - test_name += "-rejected" scenario_navigator.review_reject(test_name=test_name) else: if firmware.is_nano: end_text = "Accept" else: - end_text = "Sign" + end_text = r"(Sign|Accept (risk|threat))" + if simu_params is not None: + navigator.navigate_and_compare(default_screenshot_path, + f"{test_name}/warning", + [NavInsID.USE_CASE_CHOICE_REJECT], + screen_change_after_last_instruction=False) + scenario_navigator.review_approve(test_name=test_name, custom_screen_text=end_text) # verify signature @@ -120,11 +143,22 @@ def common_test_nft(firmware: Firmware, def common_test_nft_reject(test_fn: Callable, firmware: Firmware, backend: BackendInterface, + navigator: Navigator, scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, + test_name: str, collec: NFTCollection, action: Action): with pytest.raises(ExceptionRAPDU) as e: - test_fn(firmware, backend, scenario_navigator, collec, action, True) + test_fn(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + test_name, + collec, + action, + True) assert e.value.status == StatusWord.CONDITION_NOT_SATISFIED # ERC-721 @@ -171,28 +205,40 @@ def action_721_fixture(request) -> Action: return request.param -def test_erc721(firmware: Firmware, - backend: BackendInterface, - scenario_navigator: NavigateWithScenario, - collec_721: NFTCollection, - action_721: Action, - reject: bool = False): +def test_nft_erc721(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, + test_name: str, + collec_721: NFTCollection, + action_721: Action, + reject: bool = False): common_test_nft(firmware, backend, + navigator, scenario_navigator, + default_screenshot_path, + test_name, collec_721, action_721, reject, ERC721_PLUGIN) -def test_erc721_reject(firmware: Firmware, - backend: BackendInterface, - scenario_navigator: NavigateWithScenario): - common_test_nft_reject(test_erc721, +def test_nft_erc721_reject(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, + test_name: str): + common_test_nft_reject(test_nft_erc721, firmware, backend, + navigator, scenario_navigator, + default_screenshot_path, + test_name, collecs_721[0], actions_721[0]) @@ -246,27 +292,39 @@ def action_1155_fixture(request) -> Action: return request.param -def test_erc1155(firmware: Firmware, - backend: BackendInterface, - scenario_navigator: NavigateWithScenario, - collec_1155: NFTCollection, - action_1155: Action, - reject: bool = False): +def test_nft_erc1155(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, + test_name: str, + collec_1155: NFTCollection, + action_1155: Action, + reject: bool = False): common_test_nft(firmware, backend, + navigator, scenario_navigator, + default_screenshot_path, + test_name, collec_1155, action_1155, reject, ERC1155_PLUGIN) -def test_erc1155_reject(firmware: Firmware, - backend: BackendInterface, - scenario_navigator: NavigateWithScenario): - common_test_nft_reject(test_erc1155, +def test_nft_erc1155_reject(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, + test_name: str): + common_test_nft_reject(test_nft_erc1155, firmware, backend, + navigator, scenario_navigator, + default_screenshot_path, + test_name, collecs_1155[0], actions_1155[0]) diff --git a/tests/ragger/test_sign.py b/tests/ragger/test_sign.py index 3ac93064d8..cc542f9a2b 100644 --- a/tests/ragger/test_sign.py +++ b/tests/ragger/test_sign.py @@ -38,7 +38,7 @@ def common(firmware: Firmware, tx_params: dict, test_name: str = "", path: str = BIP32_PATH, - confirm: bool = False): + with_simu: bool = False): app_client = EthAppClient(backend) if tx_params["chainId"] == 3: @@ -55,8 +55,10 @@ def common(firmware: Firmware, # pylint: enable=line-too-long else: name = "" + ticker = "" + icon = "" - if (app_client._firmware != Firmware.NANOS) and name: + if (firmware != Firmware.NANOS) and name: app_client.provide_network_information(name, ticker, tx_params["chainId"], bytes.fromhex(icon)) with app_client.get_public_addr(bip32_path=path, display=False): @@ -64,18 +66,16 @@ def common(firmware: Firmware, _, DEVICE_ADDR, _ = ResponseParser.pk_addr(app_client.response().data) with app_client.sign(path, tx_params): - if not firmware.is_nano and confirm: + if with_simu: navigator.navigate_and_compare(default_screenshot_path, - f"{test_name}/confirm", - [NavInsID.USE_CASE_CHOICE_CONFIRM], + f"{test_name}/warning", + [NavInsID.USE_CASE_CHOICE_REJECT], screen_change_after_last_instruction=False) - if firmware.is_nano: end_text = "Accept" else: - end_text = "Sign" - - scenario_navigator.review_approve(custom_screen_text=end_text, do_comparison=test_name!="") + end_text = r"(Sign|Accept (risk|threat))" + scenario_navigator.review_approve(test_name=test_name, custom_screen_text=end_text, do_comparison=test_name!="") # verify signature vrs = ResponseParser.signature(app_client.response().data) @@ -145,12 +145,12 @@ def test_legacy_send_error(backend: BackendInterface): # Transfer bsc -def test_legacy_send_bsc(firmware: Firmware, - backend: BackendInterface, - navigator: Navigator, - scenario_navigator: NavigateWithScenario, - test_name: str, - default_screenshot_path: Path): +def test_sign_legacy_send_bsc(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path): tx_params: dict = { "nonce": 1, "gasPrice": Web3.to_wei(GAS_PRICE2, 'gwei'), @@ -163,12 +163,12 @@ def test_legacy_send_bsc(firmware: Firmware, # Transfer on network 112233445566 on Ethereum -def test_legacy_chainid(firmware: Firmware, - backend: BackendInterface, - navigator: Navigator, - scenario_navigator: NavigateWithScenario, - test_name: str, - default_screenshot_path: Path): +def test_sign_legacy_chainid(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path): tx_params: dict = { "nonce": NONCE2, "gasPrice": Web3.to_wei(GAS_PRICE, 'gwei'), @@ -211,7 +211,14 @@ def test_sign_simple(firmware: Firmware, "value": Web3.to_wei(AMOUNT2, "ether"), "chainId": CHAIN_ID } - common(firmware, backend, navigator, scenario_navigator, default_screenshot_path, tx_params, test_name, "m/44'/60'/1'/0/0") + common(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + tx_params, + test_name, + BIP32_PATH2) def test_sign_limit_nonce(firmware: Firmware, @@ -228,7 +235,14 @@ def test_sign_limit_nonce(firmware: Firmware, "value": 0x08762, "chainId": CHAIN_ID } - common(firmware, backend, navigator, scenario_navigator, default_screenshot_path, tx_params, test_name, "m/44'/60'/1'/0/0") + common(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + tx_params, + test_name, + BIP32_PATH2) def test_sign_nonce_display(firmware: Firmware, @@ -248,7 +262,14 @@ def test_sign_nonce_display(firmware: Firmware, "value": Web3.to_wei(AMOUNT2, "ether"), "chainId": CHAIN_ID } - common(firmware, backend, navigator, scenario_navigator, default_screenshot_path, tx_params, test_name, "m/44'/60'/1'/0/0") + common(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + tx_params, + test_name, + BIP32_PATH2) def test_sign_reject(backend: BackendInterface, scenario_navigator: NavigateWithScenario): @@ -260,7 +281,7 @@ def test_sign_reject(backend: BackendInterface, scenario_navigator: NavigateWith "value": Web3.to_wei(AMOUNT2, "ether"), "chainId": CHAIN_ID } - common_reject(backend, scenario_navigator, tx_params, "m/44'/60'/1'/0/0") + common_reject(backend, scenario_navigator, tx_params, BIP32_PATH2) def test_sign_error_transaction_type(backend: BackendInterface): @@ -308,4 +329,10 @@ def test_sign_eip_2930(firmware: Firmware, } ], } - common(firmware, backend, navigator, scenario_navigator, default_screenshot_path, tx_params, test_name) + common(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + tx_params, + test_name) diff --git a/tests/ragger/test_trusted_name.py b/tests/ragger/test_trusted_name.py index 36ea57479a..e6fea252a2 100644 --- a/tests/ragger/test_trusted_name.py +++ b/tests/ragger/test_trusted_name.py @@ -26,8 +26,8 @@ AMOUNT = 1.22 -@pytest.fixture(name="verbose", params=[False, True]) -def verbose_fixture(request) -> bool: +@pytest.fixture(name="verbose_ens", params=[False, True]) +def verbose_ens_fixture(request) -> bool: return request.param @@ -46,12 +46,12 @@ def test_trusted_name_v1(firmware: Firmware, backend: BackendInterface, navigator: Navigator, scenario_navigator: NavigateWithScenario, - verbose: bool, + verbose_ens: bool, test_name: str): app_client = EthAppClient(backend) challenge = common(firmware, app_client) - if verbose: + if verbose_ens: settings_toggle(firmware, navigator, [SettingID.VERBOSE_ENS]) test_name += "_verbose" diff --git a/tests/ragger/test_tx_simulation.py b/tests/ragger/test_tx_simulation.py new file mode 100644 index 0000000000..5e6606df91 --- /dev/null +++ b/tests/ragger/test_tx_simulation.py @@ -0,0 +1,391 @@ +from pathlib import Path +from enum import IntEnum +from web3 import Web3 +import pytest + +from ragger.error import ExceptionRAPDU +from ragger.backend import BackendInterface +from ragger.firmware import Firmware +from ragger.navigator import Navigator, NavInsID +from ragger.navigator.navigation_scenario import NavigateWithScenario + +from test_sign import common as sign_tx_common +from test_blind_sign import test_blind_sign as blind_sign +from test_nft import common_test_nft, collecs_721, actions_721, ERC721_PLUGIN +from test_eip191 import common as sign_eip191 +from test_eip712 import test_eip712_filtering_empty_array as sign_eip712 +from test_eip712 import test_eip712_v0 as sign_eip712_v0 +from test_gcs import test_gcs_poap as sign_gcs_poap + +from client.client import EthAppClient, StatusWord +from client.settings import SettingID, settings_toggle +from client.tx_simu import SimuType, TxSimu + + +class W3CFlags(IntEnum): + W3C_ENABLE = 0x10 + W3C_OPT_IN = 0x20 + + +@pytest.fixture(name="config", params=["benign", "threat", "warning", "issue"]) +def config_fixture(request) -> str: + return request.param + + +def __common_setting_handling(firmware: Firmware, + navigator: Navigator, + app_client: EthAppClient, + expected: bool) -> None: + """Common setting handling for the tests""" + + response = app_client.get_app_configuration() + assert response.status == StatusWord.OK + flags = response.data[0] + if bool(flags & W3CFlags.W3C_ENABLE) != expected: + # Toggle the WEB3_CHECK setting + settings_toggle(firmware, navigator, [SettingID.WEB3_CHECK]) + + +def __get_simu_params(risk: str, simu_type: SimuType) -> TxSimu: + """Common simu parameters for the tests""" + + simu_params = { + "tiny_url": "https://www.ledger.com", + "simu_type": simu_type + } + + if risk == "benign": + simu_params["risk"] = 0 + simu_params["category"] = 0 + elif risk == "warning": + simu_params["risk"] = 1 + simu_params["category"] = 4 + elif risk in ("threat", "issue"): + simu_params["risk"] = 2 + simu_params["category"] = 2 + else: + raise ValueError(f"Unknown risk value: {risk}") + + return TxSimu(**simu_params) + + +def __handle_simulation(app_client: EthAppClient, simu_params: TxSimu) -> None: + if not simu_params.tx_hash: + simu_params.tx_hash = bytes.fromhex("deadbeaf"*8) + response = app_client.provide_tx_simulation(simu_params) + assert response.status == StatusWord.OK + + +def test_tx_simulation_opt_in(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str, + default_screenshot_path: Path) -> None: + """Test the TX Simulation Opt-In feature.""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + response = app_client.get_app_configuration() + assert response.status == StatusWord.OK + assert response.data[0] & W3CFlags.W3C_OPT_IN == 0 + + with app_client.opt_in_tx_simulation(): + navigator.navigate_and_compare(default_screenshot_path, + test_name, + [NavInsID.USE_CASE_CHOICE_CONFIRM]) + + response = app_client.get_app_configuration() + assert response.status == StatusWord.OK + mask = W3CFlags.W3C_OPT_IN | W3CFlags.W3C_ENABLE + assert response.data[0] & mask == mask + + +def test_tx_simulation_disabled(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator) -> None: + """Test the TX Simulation APDU with the WEB3_CHECK setting disabled. + It should return an error + """ + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, False) + + simu_params = __get_simu_params("benign", SimuType.TRANSACTION) + simu_params.chain_id = 5 + try: + __handle_simulation(app_client, simu_params) + except ExceptionRAPDU as err: + assert err.status == StatusWord.NOT_IMPLEMENTED + else: + assert False # An exception should have been raised + + +def test_tx_simulation_enabled(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator) -> None: + """Test the TX Simulation APDU with the WEB3_CHECK setting enabled""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + simu_params = __get_simu_params("benign", SimuType.TRANSACTION) + simu_params.chain_id = 5 + __handle_simulation(app_client, simu_params) + + +def test_tx_simulation_sign(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path, + config: str) -> None: + """Test the TX Simulation APDU with a simple transaction""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + tx_params: dict = { + "nonce": 21, + "gasPrice": Web3.to_wei(13, 'gwei'), + "gas": 21000, + "to": bytes.fromhex("5a321744667052affa8386ed49e00ef223cbffc3"), + "value": Web3.to_wei(1.22, "ether"), + "chainId": 5 + } + if config != "issue": + simu_params = __get_simu_params(config, SimuType.TRANSACTION) + _, tx_hash = app_client.serialize_tx(tx_params) + simu_params.chain_id = tx_params["chainId"] + simu_params.tx_hash = tx_hash + __handle_simulation(app_client, simu_params) + + sign_tx_common(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + tx_params, + test_name + f"_{config}", + with_simu=config not in ("benign", "issue")) + + +def test_tx_simulation_no_simu(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path) -> None: + """Test the TX Transaction APDU without TX Simulation APDU + but with the WEB3_CHECK setting enabled""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + tx_params: dict = { + "nonce": 21, + "gasPrice": Web3.to_wei(13, 'gwei'), + "gas": 21000, + "to": bytes.fromhex("5a321744667052affa8386ed49e00ef223cbffc3"), + "value": Web3.to_wei(1.22, "ether"), + "chainId": 5 + } + + sign_tx_common(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + tx_params, + test_name, + with_simu=False) + + +def test_tx_simulation_nft(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + default_screenshot_path: Path, + test_name: str) -> None: + """Test the TX Simulation APDU with a Plugin & NFT transaction""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + simu_params = __get_simu_params("warning", SimuType.TRANSACTION) + + common_test_nft(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + test_name, + collecs_721[0], + actions_721[0], + False, + ERC721_PLUGIN, + simu_params) + + +def test_tx_simulation_blind_sign(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path, + config: str) -> None: + """Test the TX Simulation APDU with a Blind Sign transaction""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + if config != "issue": + simu_params = __get_simu_params(config, SimuType.TRANSACTION) + else: + simu_params = None + + test_name += f"_{config}" + blind_sign(firmware, + backend, + navigator, + scenario_navigator, + default_screenshot_path, + test_name, + False, + 0.0, + simu_params) + + +def test_tx_simulation_eip191(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path, + config: str) -> None: + """Test the TX Simulation APDU with a Message Streaming based on EIP191""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + if config in ("benign", "warning"): + pytest.skip("Skipping useless tests") + + # TODO Re-activate when partners are ready for eip191 + pytest.skip("Skip until partners are ready for eip191") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + simu_params = __get_simu_params(config, SimuType.PERSONAL_MESSAGE) + msg = "Example `personal_sign` message with TX Simulation" + if config == "issue": + msg += " and wrong hash" + simu_params.tx_hash = bytes.fromhex("deadbeaf"*8) + test_name += f"_{config}" + + sign_eip191(backend, + navigator, + scenario_navigator, + default_screenshot_path, + test_name, + msg, + simu_params) + + +def test_tx_simulation_eip712(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str, + default_screenshot_path: Path) -> None: + """Test the TX Simulation APDU with a Message Streaming based on EIP712""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + simu_params = __get_simu_params("threat", SimuType.TYPED_DATA) + + sign_eip712(firmware, + backend, + navigator, + default_screenshot_path, + test_name, + False, + simu_params) + + +def test_tx_simulation_eip712_v0(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator) -> None: + """Test the TX Simulation APDU with a Message Streaming based on EIP712_v0""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + simu_params = __get_simu_params("threat", SimuType.TYPED_DATA) + + sign_eip712_v0(firmware, + backend, + navigator, + simu_params) + + +def test_tx_simulation_gcs(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + scenario_navigator: NavigateWithScenario, + test_name: str, + default_screenshot_path: Path) -> None: + """Test the TX Simulation APDU with a Message Streaming based on EIP712""" + + if firmware.is_nano: + pytest.skip("Not yet supported on Nano") + + app_client = EthAppClient(backend) + + __common_setting_handling(firmware, navigator, app_client, True) + + simu_params = __get_simu_params("warning", SimuType.TRANSACTION) + + sign_gcs_poap(firmware, + backend, + navigator, + scenario_navigator, + test_name, + default_screenshot_path, + simu_params) diff --git a/tools/gen_dynamic_network.py b/tools/gen_dynamic_network.py index 42135830d7..1cd9303db4 100755 --- a/tools/gen_dynamic_network.py +++ b/tools/gen_dynamic_network.py @@ -3,7 +3,6 @@ import os import subprocess import sys -import struct import logging import re from hashlib import sha256 @@ -202,8 +201,7 @@ def generate_tlv_payload(name: str, # Network Icon Hash payload += format_tlv(NetworkInfoTag.NETWORK_ICON_HASH, sha256(icon).digest()) # Append the data Signature - payload += format_tlv(NetworkInfoTag.DER_SIGNATURE, - sign_data(Key.CAL, payload)) + payload += format_tlv(NetworkInfoTag.DER_SIGNATURE, sign_data(Key.NETWORK, payload)) # Return the constructed TLV payload as bytes return payload diff --git a/tools/gen_tx_simulation.py b/tools/gen_tx_simulation.py new file mode 100755 index 0000000000..d1d324c054 --- /dev/null +++ b/tools/gen_tx_simulation.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 + +import sys +import logging +from enum import IntEnum +from pathlib import Path +import argparse + +# Resolve the parent directory and append to sys.path +parent = Path(__file__).parent.parent.resolve() +client_module = Path(f"{parent}/client/src/ledger_app_clients/ethereum") +sys.path.append(f"{client_module}") +# Import the required module +from tlv import format_tlv # type: ignore +from keychain import Key, sign_data # type: ignore + + +class TxSimulationTag(IntEnum): + STRUCTURE_TYPE = 0x01 + STRUCTURE_VERSION = 0x02 + ADDRESS = 0x22 + CHAIN_ID = 0x23 + TX_HASH = 0x27 + W3C_NORMALIZED_RISK = 0x80 + W3C_NORMALIZED_CATEGORY = 0x81 + W3C_PROVIDER_MSG = 0x82 + W3C_TINY_URL = 0x83 + W3C_SIMULATION_TYPE = 0x84 + DER_SIGNATURE = 0x15 + + +STRING_MAX_LENGTH = 30 + +PROVIDE_TX_SIMULATION = 0x32 +CLA = 0xE0 + +logger = logging.getLogger(__name__) + + +# =============================================================================== +# Parameters +# =============================================================================== +def init_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="Generate hex string for TX simulation APDU.") + parser.add_argument("--addr", "-a" , help="From address") + parser.add_argument("--chainid", "-c", type=int, help="Network chain_id") + parser.add_argument("--risk", "-R", type=lambda x: int(x,0), required=True, help="Risk") + parser.add_argument("--category", "-C", type=int, required=True, help="Category") + parser.add_argument("--message", "-M", help="Provider Message") + parser.add_argument("--url", "-U", required=True, help="Report Tiny URL") + parser.add_argument("--unknown", "-u", action='store_true', help="Set TX_HASH to 0x00 to simulate unknown W3C status") + parser.add_argument("--verbose", "-v", action='store_true', help="Verbose mode") + return parser + + +# =============================================================================== +# Logging +# =============================================================================== +def set_logging(verbose: bool = False) -> None: + if verbose: + logger.setLevel(level=logging.DEBUG) + else: + logger.setLevel(level=logging.INFO) + logger.handlers.clear() + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter("[%(levelname)s] %(message)s")) + logger.addHandler(handler) + + +# =============================================================================== +# Prepare APDU - Extracted from python client +# =============================================================================== +def serialize(cdata: bytes) -> bytes: + """ + Serializes the TX Simulation information into byte format. + + Args: + cdata (bytes): The TX Simulation data to be serialized. + + Returns: + bytes: The serialized byte sequence combining the header and the data. + """ + + # Initialize a bytearray to construct the header + header = bytearray() + header.append(CLA) + header.append(PROVIDE_TX_SIMULATION) + header.append(0x00) + header.append(0x00) + header.append(len(cdata)) + # Return the concatenation of the header and cdata + return header + cdata + + +def generate_tlv_payload(risk: int, + category: int, + message: str, + url: str, + addr: str, + chain_id: int = 0, + unknown: bool = False) -> bytes: + """ + Generates a TLV (Type-Length-Value) payload for the given TX Simulation. + + Args: + risk (int): The risk value for the TX Simulation. + category (int): The category value for the TX Simulation. + message (str): The provider message for the TX Simulation. + url (str): The tiny URL for the TX Simulation. + chain_id (int): The unique identifier for the blockchain network. + unknown (bool): The flag to indicate the unknown status of the W3C. + + Returns: + bytes: The generated TLV payload. + """ + + # 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)) + 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.W3C_NORMALIZED_RISK, risk) + payload += format_tlv(TxSimulationTag.W3C_NORMALIZED_CATEGORY, category) + if message: + payload += format_tlv(TxSimulationTag.W3C_PROVIDER_MSG, message.encode('utf-8')) + payload += format_tlv(TxSimulationTag.W3C_TINY_URL, url.encode('utf-8')) + payload += format_tlv(TxSimulationTag.W3C_SIMULATION_TYPE, 0) + # Append the data Signature + payload += format_tlv(TxSimulationTag.DER_SIGNATURE, sign_data(Key.W3C, payload)) + + # Return the constructed TLV payload as bytes + return payload + + +# =============================================================================== +# Main entry +# =============================================================================== +def main() -> None: + parser = init_parser() + args = parser.parse_args() + + # Check parameters + if not 0 <= args.risk <= 2: + logger.error("Invalid risk value") + sys.exit(1) + if not 0 <= args.category <= 255: + logger.error("Invalid category value") + sys.exit(1) + if args.message and len(args.message) >= STRING_MAX_LENGTH: + logger.error("Invalid message") + sys.exit(1) + if len(args.url) >= STRING_MAX_LENGTH: + logger.error("Invalid url") + sys.exit(1) + if not args.addr: + args.addr = "Dad77910DbDFdE764fC21FCD4E74D71bBACA6D8D" + logger.warning(f"No address provided -> Forcing {args.addr}") + + set_logging(args.verbose) + + payload = generate_tlv_payload(args.risk, + args.category, + args.message, + args.url, + args.addr, + args.chainid, + args.unknown) + logger.info(f"TX Simulation Payload[{len(payload)}]: {payload.hex()}") + logger.info(f"TX Simulation APDU: {serialize(payload).hex()}") + + +if __name__ == "__main__": + main()