diff --git a/.github/workflows/build_and_functional_tests.yml b/.github/workflows/build_and_functional_tests.yml index b6d165f1..8bf79ac9 100644 --- a/.github/workflows/build_and_functional_tests.yml +++ b/.github/workflows/build_and_functional_tests.yml @@ -27,6 +27,10 @@ on: - develop pull_request: +permissions: + contents: read + packages: read + jobs: build_application: name: Build application using the reusable workflow @@ -41,3 +45,12 @@ jobs: with: download_app_binaries_artifact: "app_tezos_binaries" regenerate_snapshots: ${{ github.event_name == 'workflow_dispatch' && inputs.golden_run == 'Open a PR' }} + test_dir: "tests/standalone" + + tests_swap: + name: Run swap tests using the reusable workflow + needs: build_application + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_swap_tests.yml@v1 + with: + download_app_binaries_artifact: "app_tezos_binaries" + regenerate_snapshots: ${{ github.event_name == 'workflow_dispatch' && inputs.golden_run == 'Open a PR' }} diff --git a/.gitignore b/.gitignore index 67a8795e..de72e1de 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ integration_tests_log pattern_registry tests/samples tests/standalone/snapshots-tmp +tests/swap/snapshots-tmp +tests/swap/.test_dependencies/ unit-tests/build *env/ ledger/ diff --git a/app/Makefile b/app/Makefile index 07c80503..5e988d08 100644 --- a/app/Makefile +++ b/app/Makefile @@ -32,7 +32,7 @@ APPNAME = "Tezos Wallet" # Application version APPVERSION_M=3 APPVERSION_N=2 -APPVERSION_P=2 +APPVERSION_P=4 APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) # COMMIT diff --git a/app/src/handle_swap.c b/app/src/handle_swap.c index 5c630f8b..22828a69 100644 --- a/app/src/handle_swap.c +++ b/app/src/handle_swap.c @@ -33,6 +33,7 @@ #include "keys.h" #include "utils.h" +#include "parser/fa2_tokens.h" #include "parser/num_parser.h" // based on app-exchange @@ -40,6 +41,8 @@ #define ADDRESS_MAX_SIZE 63 /* the smallest unit is microtez */ #define DECIMALS 6 +/* Room for the ticker of a token swap, see swap_parse_config() */ +#define TICKER_MAX_SIZE 16 /* Check check_address_parameters_t.address_to_check against specified * parameters. @@ -99,6 +102,20 @@ swap_handle_get_printable_amount(get_printable_amount_parameters_t *params) FUNC_ENTER(("params=%p", params)); uint64_t amount; + char ticker[TICKER_MAX_SIZE] = TICKER; + uint8_t decimals = DECIMALS; + + /* Fees are always paid in tez, even when swapping a token. Without a coin + * configuration the currency is tez too. */ + if (!params->is_fee && (params->coin_configuration != NULL) + && (params->coin_configuration_length > 0)) { + if (!swap_parse_config(params->coin_configuration, + params->coin_configuration_length, ticker, + sizeof(ticker), &decimals)) { + PRINTF("[ERROR] Fail to parse coin configuration\n"); + goto error; + } + } if (!swap_str_to_u64(params->amount, params->amount_length, &amount)) { PRINTF("[ERROR] Fail to parse amount\n"); @@ -107,13 +124,13 @@ swap_handle_get_printable_amount(get_printable_amount_parameters_t *params) if (!format_fpu64_trimmed(params->printable_amount, sizeof(params->printable_amount), amount, - DECIMALS)) { + decimals)) { PRINTF("[ERROR] Fail to print amount\n"); goto error; } strlcat(params->printable_amount, " ", sizeof(params->printable_amount)); - strlcat(params->printable_amount, TICKER, + strlcat(params->printable_amount, ticker, sizeof(params->printable_amount)); FUNC_LEAVE(); @@ -128,6 +145,11 @@ typedef struct { uint64_t amount; uint64_t fee; /// Contains transaction fees plus reveal fees, if any. char destination_address[ADDRESS_MAX_SIZE]; + /// Set when the Exchange application gave us a coin configuration, i.e. + /// when the currency being sent is an FA2 token rather than tez. + bool is_token; + char ticker[TICKER_MAX_SIZE]; /// ticker of that token + uint8_t decimals; /// its number of decimals } swap_transaction_parameters_t; static swap_transaction_parameters_t G_swap_params; @@ -158,6 +180,21 @@ swap_copy_transaction_parameters(create_transaction_parameters_t *params) goto error; } + /* A coin configuration means the swap sends a token, not tez. Without one + * we have no way to tell which token an FA2 transfer moves, so token + * swaps are only accepted when the Exchange application provides it. */ + if ((params->coin_configuration != NULL) + && (params->coin_configuration_length > 0)) { + if (!swap_parse_config(params->coin_configuration, + params->coin_configuration_length, + params_copy.ticker, sizeof(params_copy.ticker), + ¶ms_copy.decimals)) { + PRINTF("[ERROR] Fail to parse coin configuration\n"); + goto error; + } + params_copy.is_token = true; + } + if (params->destination_address == NULL) { PRINTF("[ERROR] Destination address is null\n"); goto error; @@ -208,15 +245,49 @@ swap_check_validity(void) TZ_ASSERT(EXC_REJECT, op->nb_reveal <= 1); TZ_ASSERT(EXC_REJECT, (op->batch_index - op->nb_reveal) == 1); TZ_ASSERT(EXC_REJECT, op->last_tag == TZ_OPERATION_TAG_TRANSACTION); - TZ_ASSERT(EXC_REJECT, op->total_amount == G_swap_params.amount); TZ_ASSERT(EXC_REJECT, op->total_fee == G_swap_params.fee); - tz_format_address(op->destination, 22, dstaddr, sizeof(dstaddr)); - - PRINTF("[DEBUG] dstaddr=\"%s\"\n", dstaddr); - PRINTF("[DEBUG] G...dstaddr=\"%s\"\n", G_swap_params.destination_address); - TZ_ASSERT(EXC_REJECT, - !strcmp(dstaddr, G_swap_params.destination_address)); + if (G_swap_params.is_token) { + /* A token swap is an FA2 `transfer` call on the token contract: the + * operation carries no tez, its destination is the contract, and the + * recipient and the amount live in the Michelson parameters. */ + const fa2_token_metadata_t *token; + + TZ_ASSERT(EXC_REJECT, op->total_amount == 0); + + /* Set only when the parser decoded a single, complete transfer. + * Anything else - several transfers, an unsupported encoding, an + * amount we cannot represent - leaves it clear. */ + TZ_ASSERT(EXC_REJECT, op->fa2_swap_ok); + + /* The token being moved must be the one the swap was quoted for. The + * ticker comes from the Ledger-signed coin configuration, so matching + * it against the registry entry of the contract actually called ties + * the two together. */ + token = fa2_find_token(op->destination, op->fa2_token_id); + TZ_ASSERT(EXC_REJECT, token != NULL); + PRINTF("[DEBUG] token=\"%s\" ticker=\"%s\"\n", token->symbol, + G_swap_params.ticker); + TZ_ASSERT(EXC_REJECT, !strcmp(token->symbol, G_swap_params.ticker)); + TZ_ASSERT(EXC_REJECT, token->decimals == G_swap_params.decimals); + + PRINTF("[DEBUG] fa2 dstaddr=\"%s\"\n", op->fa2_destination); + PRINTF("[DEBUG] G...dstaddr=\"%s\"\n", + G_swap_params.destination_address); + TZ_ASSERT(EXC_REJECT, !strcmp(op->fa2_destination, + G_swap_params.destination_address)); + TZ_ASSERT(EXC_REJECT, op->fa2_amount == G_swap_params.amount); + } else { + TZ_ASSERT(EXC_REJECT, op->total_amount == G_swap_params.amount); + + tz_format_address(op->destination, 22, dstaddr, sizeof(dstaddr)); + + PRINTF("[DEBUG] dstaddr=\"%s\"\n", dstaddr); + PRINTF("[DEBUG] G...dstaddr=\"%s\"\n", + G_swap_params.destination_address); + TZ_ASSERT(EXC_REJECT, + !strcmp(dstaddr, G_swap_params.destination_address)); + } TZ_POSTAMBLE; } diff --git a/app/src/parser/operation_parser.c b/app/src/parser/operation_parser.c index ddb0ca91..d905c01b 100644 --- a/app/src/parser/operation_parser.c +++ b/app/src/parser/operation_parser.c @@ -387,8 +387,12 @@ tz_operation_parser_init(tz_parser_state *state, uint16_t size, memset(&state->operation.destination, 0, 22); op->batch_index = 0; #ifdef HAVE_SWAP - op->last_tag = TZ_OPERATION_TAG_END; - op->nb_reveal = 0; + op->last_tag = TZ_OPERATION_TAG_END; + op->nb_reveal = 0; + op->fa2_swap_ok = 0; + op->fa2_token_id = 0; + op->fa2_amount = 0; + op->fa2_destination[0] = '\0'; #endif // HAVE_SWAP op->total_fee = 0; op->total_amount = 0; @@ -623,6 +627,9 @@ tz_step_tag(tz_parser_state *state) if (t == TZ_OPERATION_TAG_REVEAL) { op->nb_reveal++; } + /* Reset per-operation: a transfer decoded in an earlier operation of the + batch must not be credited to this one. */ + op->fa2_swap_ok = 0; #endif // HAVE_SWAP op->is_fa2_candidate = 0; memset(&op->destination, 0, TZ_OPERATION_DESTINATION_SIZE); @@ -680,6 +687,45 @@ tz_step_tag(tz_parser_state *state) _Static_assert((TZ_CAPTURE_BUFFER_SIZE % 2U) == 0U, "TZ_CAPTURE_BUFFER_SIZE must be even for FA2 CAPTURE split"); +#ifdef HAVE_SWAP +/** + * @brief Convert a decimal ASCII string to a uint64. + * + * Used to keep an FA2 amount in a form swap validation can compare + * against the amount validated by the Exchange application. + * + * @param str: NUL-terminated decimal digits + * @param out: parsed value, untouched on failure + * @return bool: false if empty, not made of digits only (a leading `-` + * included), or larger than UINT64_MAX + */ +static bool +fa2_decimal_to_u64(const char *str, uint64_t *out) +{ + uint64_t value = 0; + + if ((str == NULL) || (*str == '\0')) { + return false; + } + + for (; *str != '\0'; str++) { + uint64_t digit; + + if ((*str < '0') || (*str > '9')) { + return false; + } + digit = (uint64_t)(*str - '0'); + if (value > ((UINT64_MAX - digit) / 10u)) { + return false; + } + value = (value * 10u) + digit; + } + + *out = value; + return true; +} +#endif // HAVE_SWAP + /** * @brief Format an integer token amount string with token decimals and * symbol. @@ -1129,6 +1175,23 @@ tz_step_read_fa2_transfer(tz_parser_state *state) /* Verify we are at the end of the parameter (no extra items) */ FA2_REQUIRE(state, state->ofs == op->frame->stop); +#ifdef HAVE_SWAP + /* Save what swap validation needs before the emit steps below run: + they reuse both the CAPTURE buffer and the decimal buffer, and the + frame holding token_id is popped on the way out. Anything we cannot + represent leaves fa2_swap_ok clear, which makes a swap refuse the + operation while leaving the display path untouched. */ + if (fa2_decimal_to_u64((const char *)state->buffers.num.decimal, + &op->fa2_amount) + && (strlen((const char *)(CAPTURE + FA2_TO_ADDR_OFS)) + < sizeof(op->fa2_destination))) { + STRLCPY(op->fa2_destination, + (const char *)(CAPTURE + FA2_TO_ADDR_OFS)); + op->fa2_token_id = op->frame->step_read_fa2.token_id_val; + op->fa2_swap_ok = 1; + } +#endif // HAVE_SWAP + op->frame->step_read_fa2.sub_step = FA2_STEP_EMIT_TO_ADDR; tz_continue; diff --git a/app/src/parser/operation_state.h b/app/src/parser/operation_state.h index 8bbd8fd7..0baf651f 100644 --- a/app/src/parser/operation_state.h +++ b/app/src/parser/operation_state.h @@ -254,6 +254,9 @@ typedef struct { #define TZ_OPERATION_SOURCE_SIZE 22 #define TZ_OPERATION_DESTINATION_SIZE 22 +/// Base58 Tezos addresses (tz1/tz2/tz3/tz4/KT1) are 36 characters long +#define TZ_OPERATION_FA2_ADDR_SIZE 37 + /** * @brief This struct represents the parser of operations * @@ -288,7 +291,15 @@ typedef struct { #ifdef HAVE_SWAP tz_operation_tag last_tag; /// last operations tag encountered uint16_t nb_reveal; /// number of reveal encountered -#endif // HAVE_SWAP - uint64_t total_fee; /// last fee encountered - uint64_t total_amount; /// last amount encountered + /// A single FA2 `transfer` was decoded in full. The three fields below + /// are meaningful only then. They are kept here, and not in the parser + /// frame, because swap validation reads them once parsing is over: see + /// swap_check_validity() in handle_swap.c. + uint8_t fa2_swap_ok : 1; + uint64_t fa2_token_id; /// token id of that transfer + uint64_t fa2_amount; /// its amount, in the token's smallest unit + char fa2_destination[TZ_OPERATION_FA2_ADDR_SIZE]; /// its `to_` +#endif // HAVE_SWAP + uint64_t total_fee; /// last fee encountered + uint64_t total_amount; /// last amount encountered } tz_operation_state; diff --git a/ledger_app.toml b/ledger_app.toml index 2651618d..95222265 100644 --- a/ledger_app.toml +++ b/ledger_app.toml @@ -12,3 +12,11 @@ directory = "./unit-tests/" [pytest.standalone] directory = "./tests/standalone/" + +[pytest.swap] +directory = "./tests/swap/" +[pytest.swap.dependencies] +testing_with_latest = [ + { url = "https://github.com/LedgerHQ/app-exchange", ref = "develop", use_case = "dbg_use_test_keys" }, + { url = "https://github.com/LedgerHQ/app-ethereum", ref = "develop", use_case = "use_test_keys" }, +] diff --git a/tests/standalone/snapshots/apex_p/test_menu/test_settings_menu_apex_p/00001.png b/tests/standalone/snapshots/apex_p/test_menu/test_settings_menu_apex_p/00001.png index 6e913a2d..3b7cbedf 100644 Binary files a/tests/standalone/snapshots/apex_p/test_menu/test_settings_menu_apex_p/00001.png and b/tests/standalone/snapshots/apex_p/test_menu/test_settings_menu_apex_p/00001.png differ diff --git a/tests/standalone/snapshots/flex/test_menu/test_settings_menu_flex/00001.png b/tests/standalone/snapshots/flex/test_menu/test_settings_menu_flex/00001.png index b48a8eab..0120b836 100644 Binary files a/tests/standalone/snapshots/flex/test_menu/test_settings_menu_flex/00001.png and b/tests/standalone/snapshots/flex/test_menu/test_settings_menu_flex/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_menu/test_home_menu_nanosp/00001.png b/tests/standalone/snapshots/nanosp/test_menu/test_home_menu_nanosp/00001.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanosp/test_menu/test_home_menu_nanosp/00001.png and b/tests/standalone/snapshots/nanosp/test_menu/test_home_menu_nanosp/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00001.png b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00001.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00001.png and b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00008.png b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00008.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00008.png and b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_blindsign_nanosp/00008.png differ diff --git a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00001.png b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00001.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00001.png and b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00008.png b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00008.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00008.png and b/tests/standalone/snapshots/nanosp/test_menu/test_toggle_expert_mode_nanosp/00008.png differ diff --git a/tests/standalone/snapshots/nanox/test_menu/test_home_menu_nanox/00001.png b/tests/standalone/snapshots/nanox/test_menu/test_home_menu_nanox/00001.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanox/test_menu/test_home_menu_nanox/00001.png and b/tests/standalone/snapshots/nanox/test_menu/test_home_menu_nanox/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00001.png b/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00001.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00001.png and b/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00008.png b/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00008.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00008.png and b/tests/standalone/snapshots/nanox/test_menu/test_toggle_blindsign_nanox/00008.png differ diff --git a/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00001.png b/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00001.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00001.png and b/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00008.png b/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00008.png index 35636632..b430026c 100644 Binary files a/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00008.png and b/tests/standalone/snapshots/nanox/test_menu/test_toggle_expert_mode_nanox/00008.png differ diff --git a/tests/standalone/snapshots/stax/test_menu/test_settings_menu_stax/00001.png b/tests/standalone/snapshots/stax/test_menu/test_settings_menu_stax/00001.png index edfb1e70..8e8863bb 100644 Binary files a/tests/standalone/snapshots/stax/test_menu/test_settings_menu_stax/00001.png and b/tests/standalone/snapshots/stax/test_menu/test_settings_menu_stax/00001.png differ diff --git a/tests/standalone/test_version.py b/tests/standalone/test_version.py index 40c8ff97..f751c1a1 100755 --- a/tests/standalone/test_version.py +++ b/tests/standalone/test_version.py @@ -22,7 +22,7 @@ def test_version(backend: TezosBackend): """Test that the app version is the same as the current version.""" - current_version = Version(Version.AppKind.WALLET, 3, 2, 2) + current_version = Version(Version.AppKind.WALLET, 3, 2, 4) data = backend.version() diff --git a/tests/swap/README.md b/tests/swap/README.md new file mode 100644 index 00000000..b23f0b79 --- /dev/null +++ b/tests/swap/README.md @@ -0,0 +1,75 @@ +# Swap functional tests + +These tests exercise the Tezos application as it is used by the +[Exchange application](https://ledgerhq.github.io/app-exchange/) through the +`os_lib_call` mechanism, i.e. the swap feature. That mode takes a different +launch path in the application and needs a different Speculos setup, which is +why it lives beside `tests/standalone/` rather than inside it. + +Speculos runs the Exchange application, with the Tezos application and the +Ethereum application - which serves as the payout currency - sideloaded as +libraries. + +```text +swap/ +├── cal_helper.py # Coin configurations, as the CAL would provide them +├── conftest.py # Ragger configuration and fixtures +├── tezos_transaction.py # Minimal Tezos operation encoding +├── test_swap_fa2.py # The test cases +├── helper_tool_clone_dependencies.py # Clones Exchange and Ethereum (run on the host) +├── helper_tool_build_dependencies.py # Builds them (run inside the Ledger docker image) +├── snapshots/ # Ragger UI snapshots +└── requirements.txt # Python dependencies +``` + +## Setup + +Build the Tezos application for the device you want to test, in the Ledger +docker environment, as usual. + +Then clone the Exchange and Ethereum applications, on the host: + +```sh +pip install -U GitPython +python tests/swap/helper_tool_clone_dependencies.py +``` + +And build them, from the `tests/swap` directory, inside the docker image: + +```sh +docker run --user "$(id -u)":"$(id -g)" --rm -ti -v "$(realpath .):/app" \ + "ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest" \ + python3 helper_tool_build_dependencies.py +``` + +This drops the binaries where `conftest.py` expects them: +`.test_dependencies/main/app-exchange/` and +`.test_dependencies/libraries/app-ethereum/`. + +## Running + +```sh +pip install -r tests/swap/requirements.txt +pytest tests/swap --device flex +``` + +Add `--golden_run` to regenerate the snapshots, and `-k ` to run a single +case. In CI the same is done by the `tests_swap` job, which builds the +dependencies declared under `[pytest.swap.dependencies]` in `ledger_app.toml`. + +## What is covered + +| Case | Expectation | +| --- | --- | +| `test_tezos_native_swap_control` | A native tez swap is signed. Guards the setup itself. | +| `test_tezos_fa2` | A swap paying with USDt is signed (LIVE-36514). | +| `test_tezos_fa2_tampered` | A tampered amount, destination or fee is refused. | +| `test_tezos_fa2_wrong_token` | Transferring a different registered token is refused. | +| `test_tezos_fa2_without_token_config` | Without a sub-coin configuration the swap is refused. | + +That last case is worth keeping in mind: the Exchange application forwards only +the sub-coin configuration to the coin application, never the ticker. The CAL +does not publish one for FA2 tokens on Tezos today, so the application cannot +tell which token an operation moves and refuses to sign - by design. Token +swaps only work once the CAL provides ticker and decimals, as it already does +for USDT on TON. diff --git a/tests/swap/__init__.py b/tests/swap/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/swap/_helper_tool.py b/tests/swap/_helper_tool.py new file mode 100644 index 00000000..38e3a504 --- /dev/null +++ b/tests/swap/_helper_tool.py @@ -0,0 +1,116 @@ +import os +import subprocess +from pathlib import Path + +base = Path(__file__).parent.resolve() / ".test_dependencies" + +APP_EXCHANGE_URL = "git@github.com:LedgerHQ/app-exchange.git" +APP_EXCHANGE_DIR = base / "main/app-exchange/" +APP_EXCHANGE_CLONE_DIR = base / "app-exchange/" + +APP_ETHEREUM_URL = "git@github.com:LedgerHQ/app-ethereum.git" +APP_ETHEREUM_DIR = base / "libraries/app-ethereum/" +APP_ETHEREUM_CLONE_DIR = base / "app-ethereum/" + +DEVICES_CONF = { + "nanos+": { + "sdk": "NANOSP_SDK", + "bin_path": "build/nanos2/bin/", + }, + "nanox": { + "sdk": "NANOX_SDK", + "bin_path": "build/nanox/bin/", + }, + "stax": { + "sdk": "STAX_SDK", + "bin_path": "build/stax/bin/", + }, + "flex": { + "sdk": "FLEX_SDK", + "bin_path": "build/flex/bin/", + }, + "apex_p": { + "sdk": "APEX_P_SDK", + "bin_path": "build/apex_p/bin/", + }, +} + + +def run_cmd(cmd: str, cwd: Path = Path("."), print_output: bool = False, no_throw: bool = False) -> str: + + print(f"[run_cmd] Running: '{cmd}'' inside '{cwd}'") + + ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=cwd, check=False) + if no_throw is False and ret.returncode: + print(f"[run_cmd] Error {ret.returncode} raised while running cmd: {cmd}") + print("[run_cmd] Output was:") + print(ret.stdout) + raise ValueError() + + if print_output: + print(f"[run_cmd] Output:\n{ret.stdout}") + + return ret.stdout.strip() + + +def clone_or_pull(repo_url: str, clone_dir: str): + # Only needed when cloning / pulling, not when building. + # By putting the import here we allow the script to be imported inside the docker image + from git import Repo + + git_dir = os.path.join(clone_dir, ".git") + if not os.path.exists(git_dir): + print(f"Cloning into {clone_dir}") + run_cmd(f"rm -rf {clone_dir}") + Repo.clone_from(repo_url, clone_dir, recursive=True) + else: + print(f"Pulling latest changes in {clone_dir}") + repo = Repo(clone_dir) + origin = repo.remotes.origin + origin.fetch() + repo.git.reset("--hard", "origin/develop") + + # Update submodules + print(f"Updating submodules in {clone_dir}") + run_cmd("git submodule sync", cwd=Path(clone_dir)) + run_cmd("git submodule update --init --recursive", cwd=Path(clone_dir)) + + +def build_app(clone_dir: str, flags: str): + cmd = "make clean" + run_cmd(cmd, cwd=Path(clone_dir)) + for d in DEVICES_CONF.values(): + sdk = d["sdk"] + cmd = f"make -j BOLOS_SDK=${sdk} {flags}" + run_cmd(cmd, cwd=Path(clone_dir)) + + +def copy_build_output(clone_dir: str, dest_dir: str): + run_cmd(f"mkdir -p {dest_dir}") + run_cmd(f"cp -rT {clone_dir}/build {dest_dir}/build") + + +# ==== Build app-exchange ==== +def clone_and_pull_exchange(): + clone_or_pull(APP_EXCHANGE_URL, APP_EXCHANGE_CLONE_DIR) + + +def build_and_copy_exchange(): + build_app(APP_EXCHANGE_CLONE_DIR, flags="TESTING=1 TEST_PUBLIC_KEY=1 TRUSTED_NAME_TEST_KEY=1 DEBUG=1") + copy_build_output(APP_EXCHANGE_CLONE_DIR, APP_EXCHANGE_DIR) + + +# ==== Build app-ethereum ==== +def clone_and_pull_ethereum(): + clone_or_pull(APP_ETHEREUM_URL, APP_ETHEREUM_CLONE_DIR) + + +ETHEREUM_FLAGS = ( + "COIN=ethereum CHAIN=ethereum CAL_TEST_KEY=1 DOMAIN_NAME_TEST_KEY=1 " + "SET_PLUGIN_TEST_KEY=1 NFT_TEST_KEY=1 TRUSTED_NAME_TEST_KEY=1" +) + + +def build_and_copy_ethereum(): + build_app(APP_ETHEREUM_CLONE_DIR, flags=ETHEREUM_FLAGS) + copy_build_output(APP_ETHEREUM_CLONE_DIR, APP_ETHEREUM_DIR) diff --git a/tests/swap/cal_helper.py b/tests/swap/cal_helper.py new file mode 100644 index 00000000..84bb16d7 --- /dev/null +++ b/tests/swap/cal_helper.py @@ -0,0 +1,54 @@ +# Copyright 2026 Ledger SAS + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Coin configurations, as the CAL would provide them to the Exchange application.""" + +from ledger_app_clients.exchange.cal_helper import CurrencyConfiguration +from ragger.bip import pack_derivation_path +from ragger.utils import create_currency_config + +XTZ_PATH = "m/44'/1729'/0'" +XTZ_PACKED_DERIVATION_PATH = pack_derivation_path(XTZ_PATH) + +# Native tez. +XTZ_CURRENCY_CONFIGURATION = CurrencyConfiguration( + ticker="XTZ", + conf=create_currency_config("XTZ", "Tezos"), + packed_derivation_path=XTZ_PACKED_DERIVATION_PATH, +) + +# Tether USD, an FA2 token. Only the sub-coin configuration reaches the Tezos +# application - the Exchange application forwards nothing else - so it is what +# tells the application which token the swap was quoted for. +USDT_CURRENCY_CONFIGURATION = CurrencyConfiguration( + ticker="USDt", + conf=create_currency_config("USDt", "Tezos", sub_coin_config=("USDt", 6)), + packed_derivation_path=XTZ_PACKED_DERIVATION_PATH, +) + +# The same token as the CAL describes it today: no sub-coin configuration at +# all, which leaves the application unable to tell which token is being moved. +USDT_NO_TOKEN_CONFIGURATION = CurrencyConfiguration( + ticker="USDt", + conf=create_currency_config("USDt", "Tezos"), + packed_derivation_path=XTZ_PACKED_DERIVATION_PATH, +) + +# Contracts from the registry in app/src/parser/fa2_tokens.c. +# KT1XnTn74bUtxHfDtBmm2bGZAQfhPbvKWR8o, "Tether USD" / USDt, 6 decimals. +USDT_CONTRACT_HASH = bytes.fromhex("fe810959c3d6127a41cbd471e7cb4e91a61b780b") +USDT_TOKEN_ID = 0 +# KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb, "Quipuswap Governance" / QUIPU. It has +# 6 decimals too, so only the ticker tells it apart from USDt. +QUIPU_CONTRACT_HASH = bytes.fromhex("05001a8af813094ee8bf162ac2093a8937e8ba83") diff --git a/tests/swap/conftest.py b/tests/swap/conftest.py new file mode 100644 index 00000000..0094d0ed --- /dev/null +++ b/tests/swap/conftest.py @@ -0,0 +1,69 @@ +# Copyright 2026 Ledger SAS + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Conftest for the swap tests. + +In this suite the Tezos application is not the application under test but a +library, called by the Exchange application through os_lib_call(). Speculos is +therefore started on Exchange, with the Tezos application - and Ethereum, which +serves as the payout currency - sideloaded. + +Note that, unlike tests/standalone, no custom seed is set: the swap addresses +below are those of the default Speculos seed. +""" + +from pathlib import Path + +import pytest +from ledger_app_clients.exchange.navigation_helper import ExchangeNavigationHelper +from ragger.conftest import configuration + +########################### +### CONFIGURATION START ### +########################### + +configuration.OPTIONAL.BACKEND_SCOPE = "class" +# Exchange, the application Speculos starts. See tests/swap/README.md for how +# to populate these directories. +configuration.OPTIONAL.MAIN_APP_DIR = "tests/swap/.test_dependencies/main" +# Ethereum, sideloaded so Exchange can check the payout address. +configuration.OPTIONAL.SIDELOADED_APPS_DIR = "tests/swap/.test_dependencies/libraries/" + +######################### +### CONFIGURATION END ### +######################### + +# Pull all features from the base ragger conftest using the overridden configuration +pytest_plugins = ("ragger.conftest.base_conftest",) + + +@pytest.fixture(scope="session") +def snapshots_path(): + """Provide the default path for screenshots, used by ExchangeNavigationHelper.""" + return Path(__file__).parent.resolve() + + +@pytest.fixture(scope="function") +def exchange_navigation_helper(backend, navigator, snapshots_path, test_name): + """Drive the Exchange screens and compare them against the snapshots.""" + return ExchangeNavigationHelper(backend=backend, navigator=navigator, snapshots_path=snapshots_path, test_name=test_name) + + +def pytest_collection_modifyitems(config, items): + """Keep the parametrized tests in node id order. + + Pytest reorders tests using parametrize by alphabetical order of the + parameter, which breaks the backend scope optimisation. + """ + items[:] = sorted(items, key=lambda item: item.nodeid) diff --git a/tests/swap/helper_tool_build_dependencies.py b/tests/swap/helper_tool_build_dependencies.py new file mode 100644 index 00000000..3cde9dcf --- /dev/null +++ b/tests/swap/helper_tool_build_dependencies.py @@ -0,0 +1,9 @@ +# Run this python script inside the Ledger docker image + +# This script will build the Ethereum and Exchange application that are needed for the Swap test setup +# Run the helper script helper_tool_clone_dependencies.py first to pull them in the correct location + +from _helper_tool import build_and_copy_ethereum, build_and_copy_exchange + +build_and_copy_exchange() +build_and_copy_ethereum() diff --git a/tests/swap/helper_tool_clone_dependencies.py b/tests/swap/helper_tool_clone_dependencies.py new file mode 100644 index 00000000..10edcdb1 --- /dev/null +++ b/tests/swap/helper_tool_clone_dependencies.py @@ -0,0 +1,7 @@ +# This script will clone the Ethereum and Exchange application that are needed for the Swap test setup +# Run the helper script helper_tool_build_dependencies.py after to build and dispatch them in the correct location + +from _helper_tool import clone_and_pull_ethereum, clone_and_pull_exchange + +clone_and_pull_exchange() +clone_and_pull_ethereum() diff --git a/tests/swap/requirements.txt b/tests/swap/requirements.txt new file mode 100644 index 00000000..118f6221 --- /dev/null +++ b/tests/swap/requirements.txt @@ -0,0 +1,5 @@ +ragger[tests,speculos] >= 1.44.0 +protobuf +base58 +ledger_app_clients.exchange >= 0.0.4 +GitPython diff --git a/tests/swap/setup.cfg b/tests/swap/setup.cfg new file mode 100644 index 00000000..f1b54e36 --- /dev/null +++ b/tests/swap/setup.cfg @@ -0,0 +1,2 @@ +[tool:pytest] +addopts = --strict-markers diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png new file mode 100644 index 00000000..4aba0a2b Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png new file mode 100644 index 00000000..8ade48bc Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00000.png new file mode 100644 index 00000000..92a98828 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00001.png new file mode 100644 index 00000000..a9c9be95 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00002.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00002.png new file mode 100644 index 00000000..93f61f2a Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_swap_fa2_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png new file mode 100644 index 00000000..244bdbcf Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png new file mode 100644 index 00000000..8ade48bc Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png new file mode 100644 index 00000000..92a98828 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png new file mode 100644 index 00000000..a9c9be95 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png new file mode 100644 index 00000000..93f61f2a Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png new file mode 100644 index 00000000..244bdbcf Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png new file mode 100644 index 00000000..8ade48bc Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png new file mode 100644 index 00000000..92a98828 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png new file mode 100644 index 00000000..a9c9be95 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png new file mode 100644 index 00000000..93f61f2a Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png new file mode 100644 index 00000000..244bdbcf Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png new file mode 100644 index 00000000..8ade48bc Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png new file mode 100644 index 00000000..92a98828 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png new file mode 100644 index 00000000..a9c9be95 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png new file mode 100644 index 00000000..93f61f2a Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png new file mode 100644 index 00000000..244bdbcf Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png new file mode 100644 index 00000000..8ade48bc Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png new file mode 100644 index 00000000..92a98828 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png new file mode 100644 index 00000000..3bb67b47 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png new file mode 100644 index 00000000..93f61f2a Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png new file mode 100644 index 00000000..244bdbcf Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png new file mode 100644 index 00000000..8ade48bc Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png new file mode 100644 index 00000000..92a98828 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png new file mode 100644 index 00000000..a9c9be95 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png new file mode 100644 index 00000000..93f61f2a Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png new file mode 100644 index 00000000..4aba0a2b Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png new file mode 100644 index 00000000..8ade48bc Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png new file mode 100644 index 00000000..3e41a0c9 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png new file mode 100644 index 00000000..93210ed5 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png new file mode 100644 index 00000000..a1103595 Binary files /dev/null and b/tests/swap/snapshots/apex_p/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png new file mode 100644 index 00000000..435aa78b Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png new file mode 100644 index 00000000..261cb973 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00000.png new file mode 100644 index 00000000..3a078866 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00001.png new file mode 100644 index 00000000..4062ea51 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00002.png b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00002.png new file mode 100644 index 00000000..24d93d6e Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_swap_fa2_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png new file mode 100644 index 00000000..920d70a6 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png new file mode 100644 index 00000000..261cb973 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png new file mode 100644 index 00000000..3a078866 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png new file mode 100644 index 00000000..4062ea51 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png new file mode 100644 index 00000000..24d93d6e Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png new file mode 100644 index 00000000..920d70a6 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png new file mode 100644 index 00000000..261cb973 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png new file mode 100644 index 00000000..3a078866 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png new file mode 100644 index 00000000..4062ea51 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png new file mode 100644 index 00000000..24d93d6e Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png new file mode 100644 index 00000000..920d70a6 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png new file mode 100644 index 00000000..261cb973 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png new file mode 100644 index 00000000..3a078866 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png new file mode 100644 index 00000000..4062ea51 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png new file mode 100644 index 00000000..24d93d6e Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png new file mode 100644 index 00000000..920d70a6 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png new file mode 100644 index 00000000..261cb973 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png new file mode 100644 index 00000000..3a078866 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png new file mode 100644 index 00000000..1555793f Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png new file mode 100644 index 00000000..24d93d6e Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png new file mode 100644 index 00000000..920d70a6 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png new file mode 100644 index 00000000..261cb973 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png new file mode 100644 index 00000000..3a078866 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png new file mode 100644 index 00000000..4062ea51 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png new file mode 100644 index 00000000..24d93d6e Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png new file mode 100644 index 00000000..435aa78b Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png new file mode 100644 index 00000000..261cb973 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png new file mode 100644 index 00000000..4df43209 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png new file mode 100644 index 00000000..5632b2d1 Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png new file mode 100644 index 00000000..0722cc1a Binary files /dev/null and b/tests/swap/snapshots/flex/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png new file mode 100644 index 00000000..3a161194 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00002.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00003.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00003.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00004.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00004.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00005.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_swap_fa2_valid_1/review/00005.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00003.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00003.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00004.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00004.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00005.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_amount/review/00005.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00003.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00003.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00004.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00004.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00005.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_destination/review/00005.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00003.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00003.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00004.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00004.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00005.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_tampered_swap_wrong_fees/review/00005.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png new file mode 100644 index 00000000..b500a5d9 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00003.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00003.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00004.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00004.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00005.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00005.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00003.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00003.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00004.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00004.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00005.png b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00005.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png new file mode 100644 index 00000000..3a161194 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png new file mode 100644 index 00000000..2b8f1b3d Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png new file mode 100644 index 00000000..b1cbb143 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00003.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00003.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00004.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00004.png differ diff --git a/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00005.png b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanosp/test_tezos_native_swap_control_swap_native_valid_1/review/00005.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png new file mode 100644 index 00000000..3a161194 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00002.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00003.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00003.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00004.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00004.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00005.png b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_swap_fa2_valid_1/review/00005.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00003.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00003.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00004.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00004.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00005.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_amount/review/00005.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00003.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00003.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00004.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00004.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00005.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_destination/review/00005.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00003.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00003.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00004.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00004.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00005.png b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_tampered_swap_wrong_fees/review/00005.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png new file mode 100644 index 00000000..b500a5d9 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00003.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00003.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00004.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00004.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00005.png b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00005.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png new file mode 100644 index 00000000..f777ae54 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png new file mode 100644 index 00000000..aea8e3be Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png new file mode 100644 index 00000000..8ac0cac4 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00003.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00003.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00004.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00004.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00005.png b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00005.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png new file mode 100644 index 00000000..3a161194 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png new file mode 100644 index 00000000..95728b4e Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png new file mode 100644 index 00000000..2b8f1b3d Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png new file mode 100644 index 00000000..1a80bb27 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png new file mode 100644 index 00000000..b1cbb143 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00003.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00003.png new file mode 100644 index 00000000..2b847e35 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00003.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00004.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00004.png new file mode 100644 index 00000000..c610bf08 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00004.png differ diff --git a/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00005.png b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00005.png new file mode 100644 index 00000000..c2d3d181 Binary files /dev/null and b/tests/swap/snapshots/nanox/test_tezos_native_swap_control_swap_native_valid_1/review/00005.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png new file mode 100644 index 00000000..ceda6a87 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png new file mode 100644 index 00000000..6c80008b Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00000.png new file mode 100644 index 00000000..e91e391f Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00001.png new file mode 100644 index 00000000..e007507e Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00002.png b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00002.png new file mode 100644 index 00000000..f13420a0 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_swap_fa2_valid_1/review/00002.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png new file mode 100644 index 00000000..3ee1f43d Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png new file mode 100644 index 00000000..6c80008b Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/post_sign/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png new file mode 100644 index 00000000..e91e391f Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png new file mode 100644 index 00000000..e007507e Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png new file mode 100644 index 00000000..f13420a0 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_amount/review/00002.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png new file mode 100644 index 00000000..3ee1f43d Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png new file mode 100644 index 00000000..6c80008b Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/post_sign/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png new file mode 100644 index 00000000..e91e391f Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png new file mode 100644 index 00000000..e007507e Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png new file mode 100644 index 00000000..f13420a0 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_destination/review/00002.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png new file mode 100644 index 00000000..3ee1f43d Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png new file mode 100644 index 00000000..6c80008b Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/post_sign/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png new file mode 100644 index 00000000..e91e391f Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png new file mode 100644 index 00000000..e007507e Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png new file mode 100644 index 00000000..f13420a0 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_tampered_swap_wrong_fees/review/00002.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png new file mode 100644 index 00000000..3ee1f43d Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png new file mode 100644 index 00000000..6c80008b Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/post_sign/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png new file mode 100644 index 00000000..e91e391f Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png new file mode 100644 index 00000000..e336b3bc Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png new file mode 100644 index 00000000..f13420a0 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_without_token_config_swap_fa2_no_config/review/00002.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png new file mode 100644 index 00000000..3ee1f43d Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png new file mode 100644 index 00000000..6c80008b Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/post_sign/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png new file mode 100644 index 00000000..e91e391f Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png new file mode 100644 index 00000000..e007507e Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png new file mode 100644 index 00000000..f13420a0 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_fa2_wrong_token_swap_fa2_wrong_token/review/00002.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png new file mode 100644 index 00000000..ceda6a87 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png new file mode 100644 index 00000000..6c80008b Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/post_sign/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png new file mode 100644 index 00000000..76fea254 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00000.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png new file mode 100644 index 00000000..13ab8b60 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00001.png differ diff --git a/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png new file mode 100644 index 00000000..33342535 Binary files /dev/null and b/tests/swap/snapshots/stax/test_tezos_native_swap_control_swap_native_valid_1/review/00002.png differ diff --git a/tests/swap/test_swap_fa2.py b/tests/swap/test_swap_fa2.py new file mode 100644 index 00000000..53a2d84d --- /dev/null +++ b/tests/swap/test_swap_fa2.py @@ -0,0 +1,201 @@ +# Copyright 2026 Ledger SAS + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Swapping an FA2 token held on Tezos (LIVE-36514). + +A swap paying with a token signs an FA2 `transfer` call rather than a tez +transfer: the operation carries no tez, its destination is the token contract, +and the recipient and the amount are inside the Michelson parameters. The +application used to compare the operation against the swap parameters as if it +were a native transfer, and answered 0x6985 to every such signature. + +swap_check_validity() in app/src/handle_swap.c now branches on whether the +Exchange application provided a coin configuration. Without one the +application cannot tell which token the operation moves, so it must keep +refusing - which is what happens with the CAL configuration in production +today, see USDT_NO_TOKEN_CONFIGURATION. +""" + +import pytest +from ledger_app_clients.exchange.test_runner import ExchangeTestRunner +from ragger.error import ExceptionRAPDU + +from . import cal_helper as cal +from .tezos_transaction import ( + CLA, + EXC_REJECT, + INS_GET_PUBLIC_KEY, + INS_SIGN, + P1_FIRST, + P1_LAST, + P2_ED25519, + STATUS_OK, + blake2_hash_pubkey, + craft_fa2_transfer, + craft_native_transfer, + encode_tz1, +) + + +class TezosFa2Tests(ExchangeTestRunner): + """Swap paying with an FA2 token.""" + + currency_configuration = cal.USDT_CURRENCY_CONFIGURATION + + # The token the final transaction transfers. Overridden below by the case + # that transfers a token other than the one being swapped. + token_contract_hash = cal.USDT_CONTRACT_HASH + token_id = cal.USDT_TOKEN_ID + + # Payin address of the swap provider, i.e. the FA2 `to_` of the transfer. + valid_destination_1 = "tz1drcp5n9mkJ2eDQQsHBBSDetKJ9s5aKox4" + valid_destination_2 = "tz1TNKZitanSzHmkxVRriDdMU7qrQukae9Yr" + + # Address of the Speculos seed on cal.XTZ_PATH. It is both the refund + # address of the swap and the FA2 `from_` of the transfer. + valid_refund = "tz1YPjCVqgimTAPmxZX9egDeTFRCmrTRqmp9" + + # 100.106851 USDt, the amount of the reported failure. + valid_send_amount_1 = 100106851 + valid_send_amount_2 = 446739662 + # Operation fees, in mutez. + valid_fees_1 = 2000 + valid_fees_2 = 10078 + + fake_refund = "abcdabcd" + fake_payout = "abcdabcd" + + signature_refusal_error_code = EXC_REJECT + + def _get_device_address(self): + """Read the device public key and derive its tz1 address.""" + rapdu = self.backend.exchange(CLA, INS_GET_PUBLIC_KEY, P1_FIRST, P2_ED25519, cal.XTZ_PACKED_DERIVATION_PATH) + assert rapdu.status == STATUS_OK + source_hash = blake2_hash_pubkey(rapdu.data[2:]) + return encode_tz1(source_hash), source_hash + + def _sign(self, payload): + """Send a payload through the two packets of an INS_SIGN exchange. + + A non-9000 answer raises, so the tampering cases can expect it. + """ + rapdu = self.backend.exchange(CLA, INS_SIGN, P1_FIRST, P2_ED25519, cal.XTZ_PACKED_DERIVATION_PATH) + assert rapdu.status == STATUS_OK + self.backend.exchange(CLA, INS_SIGN, P1_LAST, P2_ED25519, data=payload) + + def perform_final_tx(self, destination, send_amount, fees, memo): + """Sign an FA2 `transfer` of `send_amount` tokens to `destination`.""" + source, source_hash = self._get_device_address() + assert source == self.valid_refund, f"Unexpected device address {source}, expected {self.valid_refund}" + + self._sign( + craft_fa2_transfer(source, source_hash, self.token_contract_hash, destination, self.token_id, send_amount, fees) + ) + + def perform_test_swap_fa2_valid_1(self): + """The reported flow: swapping USDt must be signed.""" + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + try: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + except ExceptionRAPDU as e: + pytest.fail( + f"The application refused to sign the FA2 token transfer with SW " + f"0x{e.status:04x}. The operation moves {self.valid_send_amount_1} units " + f"of USDt to {self.valid_destination_1}, both taken from the Michelson " + f"parameters, and carries 0 mutez." + ) + self.assert_exchange_is_started() + + def perform_test_swap_fa2_wrong_token(self): + """Transferring a token other than the one quoted must be refused.""" + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + assert e.value.status == self.signature_refusal_error_code + self.assert_exchange_is_started() + + +class TezosFa2WrongTokenTests(TezosFa2Tests): + """Swap quoted for USDt, but the operation transfers QUIPU instead. + + Both tokens are in the application registry and both have 6 decimals, so + only the ticker from the coin configuration tells them apart. + """ + + token_contract_hash = cal.QUIPU_CONTRACT_HASH + + +class TezosFa2NoTokenConfigTests(TezosFa2Tests): + """The situation in production: the CAL sends no sub-coin configuration. + + The application is then told nothing about the token, so it cannot check + that the operation moves the token the swap was quoted for. Refusing is + the only safe answer. + """ + + currency_configuration = cal.USDT_NO_TOKEN_CONFIGURATION + + def perform_test_swap_fa2_no_config(self): + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + assert e.value.status == self.signature_refusal_error_code + self.assert_exchange_is_started() + + +class TezosNativeSwapTests(TezosFa2Tests): + """Control case: the same flow with a native tez transfer. + + It shares everything with TezosFa2Tests except the final transaction, so a + failure here means the test setup is broken rather than the application. + """ + + currency_configuration = cal.XTZ_CURRENCY_CONFIGURATION + valid_send_amount_1 = 10000000 + + def perform_final_tx(self, destination, send_amount, fees, memo): + _, source_hash = self._get_device_address() + self._sign(craft_native_transfer(source_hash, destination, send_amount, fees)) + + def perform_test_swap_native_valid_1(self): + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + self.assert_exchange_is_started() + + +# Use a class to reuse the same Speculos instance +class TestsTezosSwap: + @pytest.mark.parametrize("test_to_run", ["swap_native_valid_1"]) + def test_tezos_native_swap_control(self, backend, exchange_navigation_helper, test_to_run): + """Sanity check: a native tez swap goes through with this exact setup.""" + TezosNativeSwapTests(backend, exchange_navigation_helper).run_test(test_to_run) + + @pytest.mark.parametrize("test_to_run", ["swap_fa2_valid_1"]) + def test_tezos_fa2(self, backend, exchange_navigation_helper, test_to_run): + TezosFa2Tests(backend, exchange_navigation_helper).run_test(test_to_run) + + @pytest.mark.parametrize("test_to_run", ["swap_wrong_amount", "swap_wrong_destination", "swap_wrong_fees"]) + def test_tezos_fa2_tampered(self, backend, exchange_navigation_helper, test_to_run): + """A tampered FA2 transfer must not be signed.""" + TezosFa2Tests(backend, exchange_navigation_helper).run_test(test_to_run) + + @pytest.mark.parametrize("test_to_run", ["swap_fa2_wrong_token"]) + def test_tezos_fa2_wrong_token(self, backend, exchange_navigation_helper, test_to_run): + """Transferring another registered token must not be signed.""" + TezosFa2WrongTokenTests(backend, exchange_navigation_helper).run_test(test_to_run) + + @pytest.mark.parametrize("test_to_run", ["swap_fa2_no_config"]) + def test_tezos_fa2_without_token_config(self, backend, exchange_navigation_helper, test_to_run): + """An FA2 swap with no sub-coin configuration must stay refused.""" + TezosFa2NoTokenConfigTests(backend, exchange_navigation_helper).run_test(test_to_run) diff --git a/tests/swap/tezos_transaction.py b/tests/swap/tezos_transaction.py new file mode 100644 index 00000000..eecf03d2 --- /dev/null +++ b/tests/swap/tezos_transaction.py @@ -0,0 +1,143 @@ +# Copyright 2026 Ledger SAS + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Minimal Tezos operation encoding, enough to craft the transactions a swap signs.""" + +from hashlib import blake2b, sha256 + +from base58 import b58decode, b58encode + +CLA = 0x80 +INS_GET_PUBLIC_KEY = 0x02 +INS_SIGN = 0x04 +P1_FIRST = 0x00 +P1_LAST = 0x81 +P2_ED25519 = 0x00 + +MAGIC_BYTE_UNSAFE = 0x03 +OPERATION_TAG_TRANSACTION = 0x6C + +STATUS_OK = 0x9000 +EXC_REJECT = 0x6985 + +# Micheline "prim with 2 arguments, no annotation" (0x07) applied to Pair (0x07) +MICHELINE_PAIR = b"\x07\x07" + +TZ1_PREFIX = bytes.fromhex("06a19f") + + +def encode_tz1(blake2_hashed_pubkey: bytes) -> str: + """Base58 encode a 20 byte public key hash as a tz1 address.""" + checksum = sha256(sha256(TZ1_PREFIX + blake2_hashed_pubkey).digest()).digest()[:4] + return b58encode(TZ1_PREFIX + blake2_hashed_pubkey + checksum).decode() + + +def decode_tz1(address: str) -> bytes: + """Extract the 20 byte public key hash out of a tz1 address.""" + return b58decode(address)[3:-4] + + +def blake2_hash_pubkey(pubkey: bytes) -> bytes: + """Hash a public key the way Tezos derives an address from it.""" + return blake2b(pubkey, digest_size=20).digest() + + +def zarith(value: int) -> bytes: + """Unsigned zarith: 7 bits per byte, the MSB being the continuation bit.""" + assert value >= 0 + if value == 0: + return b"\x00" + out = b"" + while value: + byte = value & 0x7F + value >>= 7 + out += bytes([byte | 0x80]) if value else bytes([byte]) + return out + + +def zarith_signed(value: int) -> bytes: + """Signed zarith, as used by Micheline ints: bit 6 of the first byte is the sign.""" + negative = value < 0 + value = abs(value) + first = value & 0x3F + value >>= 6 + out = bytes([first | (0x40 if negative else 0x00) | (0x80 if value else 0x00)]) + while value: + byte = value & 0x7F + value >>= 7 + out += bytes([byte | 0x80]) if value else bytes([byte]) + return out + + +def micheline_int(value: int) -> bytes: + return b"\x00" + zarith_signed(value) + + +def micheline_string(value: str) -> bytes: + raw = value.encode() + return b"\x01" + len(raw).to_bytes(4, "big") + raw + + +def micheline_sequence(payload: bytes) -> bytes: + return b"\x02" + len(payload).to_bytes(4, "big") + payload + + +def fa2_transfer_parameters(source: str, destination: str, token_id: int, amount: int) -> bytes: + """Parameters of an FA2 `transfer` entrypoint call. + + Pair(from_, [Pair(to_, Pair(token_id, amount))]), which is what Ledger Live + sends for a token transfer. + """ + transfer = MICHELINE_PAIR + micheline_string(destination) + MICHELINE_PAIR + micheline_int(token_id) + micheline_int(amount) + return micheline_sequence(MICHELINE_PAIR + micheline_string(source) + micheline_sequence(transfer)) + + +def _operation_header(source_hash: bytes, fees: int) -> bytes: + """Magic byte, branch and the manager fields shared by every transaction.""" + payload = bytes([MAGIC_BYTE_UNSAFE]) + payload += bytes(32) # branch, not checked by the application + payload += bytes([OPERATION_TAG_TRANSACTION]) + payload += b"\x00" + source_hash # implicit tz1 source + payload += zarith(fees) + payload += zarith(174728483) # counter + payload += zarith(3551) # gas limit + payload += zarith(0) # storage limit + return payload + + +def craft_native_transfer(source_hash: bytes, destination: str, amount: int, fees: int) -> bytes: + """A plain tez transfer to an implicit account.""" + payload = _operation_header(source_hash, fees) + payload += zarith(amount) + payload += b"\x00\x00" + decode_tz1(destination) # implicit tz1 destination + payload += b"\x00" # no parameters + return payload + + +def craft_fa2_transfer( + source: str, source_hash: bytes, contract_hash: bytes, destination: str, token_id: int, amount: int, fees: int +) -> bytes: + """An FA2 `transfer` call on a token contract. + + The operation carries no tez, its destination is the token contract, and + the recipient and the amount are inside the Michelson parameters. + """ + payload = _operation_header(source_hash, fees) + payload += zarith(0) + payload += b"\x01" + contract_hash + b"\x00" # originated KT1 destination + payload += b"\xff" # parameters present + payload += b"\xff" + bytes([len("transfer")]) + b"transfer" + parameters = fa2_transfer_parameters(source, destination, token_id, amount) + payload += len(parameters).to_bytes(4, "big") + parameters + return payload diff --git a/unit-tests/CMakeLists.txt b/unit-tests/CMakeLists.txt index 839f2e0a..5c70a3ec 100644 --- a/unit-tests/CMakeLists.txt +++ b/unit-tests/CMakeLists.txt @@ -12,6 +12,8 @@ enable_testing() set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) add_definitions(-DPRINTF=) +# Compile the swap-only parser state so that swap validation can be tested +add_definitions(-DHAVE_SWAP) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -pedantic -g -O0 --coverage") set(GCC_COVERAGE_LINK_FLAGS "--coverage -lgcov") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}") diff --git a/unit-tests/test_operation_parser.c b/unit-tests/test_operation_parser.c index 1b2181ee..a0724591 100644 --- a/unit-tests/test_operation_parser.c +++ b/unit-tests/test_operation_parser.c @@ -199,6 +199,36 @@ check_field_complexity(operation_parser_data *data, char *str, } } +#ifdef HAVE_SWAP +/* Parse a whole operation, discarding what it prints. Used to inspect the + parser state a swap validation would see. */ +static void +parse_to_completion(operation_parser_data *data, char *str) +{ + fill_data_str(data, str); + tz_operation_parser_set_size(data->state, (uint16_t)data->str_len); + tz_parser_state *st = data->state; + while (true) { + while (!TZ_IS_BLOCKED(tz_operation_parser_step(st))) { + } + switch (st->errno) { + case TZ_BLO_FEED_ME: + refill(data); + tz_parser_refill(st, data->ibuf, data->ilen); + continue; + case TZ_BLO_IM_FULL: + tz_parser_flush(st, data->obuf, data->olen); + continue; + case TZ_BLO_DONE: + return; + default: + fail_msg("%s:%d parsing error: %s", __FILE__, __LINE__, + tz_parser_result_name(st->errno)); + } + } +} +#endif // HAVE_SWAP + static void check_parser_error(operation_parser_data *data, char *str, tz_parser_result expected) @@ -1200,6 +1230,73 @@ test_check_fa2_transfer_clear_signing_token_id_gt0(void **state) check_field_complexity(data, str, fields_check, sizeof(fields_check)); } +#ifdef HAVE_SWAP +/* LIVE-36514: a swap paying with an FA2 token signs a `transfer` call, so the + recipient and the amount are inside the Michelson parameters and the + operation itself carries no tez. Check that the parser hands + swap_check_validity() what it needs to match them against the parameters + the Exchange application validated. + + This is the operation Ledger Live sent when swapping 100.106851 USDt, with + its branch zeroed. */ +static void +test_check_fa2_transfer_swap_fields(void **state) +{ + operation_parser_data *data = *state; + char str[] + = "030000000000000000000000000000000000000000000000000000000000000000" + "6c008be5357b478d9828ede4620a9e7ff9f4016693e1d00fa3caa853df1b0000" + "01fe810959c3d6127a41cbd471e7cb4e91a61b780b00ffff087472616e736665" + "7200000069020000006407070100000024747a3159506a43567167696d544150" + "6d785a583965674465544652436d725452716d70390200000034070701000000" + "24747a3164726370356e396d6b4a326544515173484242534465744b4a397335" + "614b6f78340707000000a389bc5f"; + /* KT1XnTn74bUtxHfDtBmm2bGZAQfhPbvKWR8o, the Tether USD contract */ + const uint8_t usdt_contract[TZ_OPERATION_DESTINATION_SIZE] + = {0x01, 0xfe, 0x81, 0x09, 0x59, 0xc3, 0xd6, 0x12, 0x7a, 0x41, 0xcb, + 0xd4, 0x71, 0xe7, 0xcb, 0x4e, 0x91, 0xa6, 0x1b, 0x78, 0x0b, 0x00}; + + parse_to_completion(data, str); + + assert_int_equal(data->state->operation.total_fee, 2000); + /* A contract call moves no tez. Comparing this against the swap amount is + what used to make the application reject the operation. */ + assert_int_equal(data->state->operation.total_amount, 0); + assert_memory_equal(data->state->operation.destination, usdt_contract, + sizeof(usdt_contract)); + + assert_true(data->state->operation.fa2_swap_ok); + assert_int_equal(data->state->operation.fa2_token_id, 0); + assert_int_equal(data->state->operation.fa2_amount, 100106851); + assert_string_equal(data->state->operation.fa2_destination, + "tz1drcp5n9mkJ2eDQQsHBBSDetKJ9s5aKox4"); +} + +/* A transfer the FA2 decoder cannot handle falls back to raw Micheline. There + is then no validated recipient or amount, so a swap must refuse it. */ +static void +test_check_fa2_transfer_swap_fields_unset_on_fallback(void **state) +{ + operation_parser_data *data = *state; + char str[] + = "030000000000000000000000000000000000000000000000000000000000000000" + "6c00ffdd6102321bc251e4a5190ad5b12b251069d9b4e807016464000105001a8a" + "f813094ee8bf162ac2093a8937e8ba830001ff087472616e736665720000009902" + "00000094070701000000244b543151576462415376615458573847576668664e68" + "33" + "4a4d6a6758766e5a4141544a570200000064070701000000247372314d79437752" + "38" + "33685a70684353716159535141705078504d65796b734a57576e680707000000a4" + "01070701000000247372314d794377523833685a70684353716159535141705078" + "50" + "4d65796b734a57576e6807070000008803"; + + parse_to_completion(data, str); + + assert_false(data->state->operation.fa2_swap_ok); +} +#endif // HAVE_SWAP + static void test_check_fa2_transfer_multi_item_fallback(void **state) { @@ -1419,6 +1516,11 @@ main(void) OPERATION_PARSER_TEST( test_check_fa2_transfer_negative_amount_fallback), OPERATION_PARSER_TEST(test_check_fa2_transfer_whole_number_amount), +#ifdef HAVE_SWAP + OPERATION_PARSER_TEST(test_check_fa2_transfer_swap_fields), + OPERATION_PARSER_TEST( + test_check_fa2_transfer_swap_fields_unset_on_fallback), +#endif // HAVE_SWAP }; return cmocka_run_group_tests(tests, NULL, NULL);