Skip to content

Commit

Permalink
Merge pull request #22 from LedgerHQ/fbe/post_trip_improvements
Browse files Browse the repository at this point in the history
Uniswap protocol update
  • Loading branch information
fbeutin-ledger authored Jan 8, 2025
2 parents 7f7031a + e382deb commit d26bee7
Show file tree
Hide file tree
Showing 1,956 changed files with 601 additions and 236 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ APPNAME = "Uniswap"

# Application version
APPVERSION_M = 1
APPVERSION_N = 3
APPVERSION_P = 0
APPVERSION_N = 4
APPVERSION_P = 2

APP_SOURCE_FILES += $(BOLOS_SDK)/lib_standard_app/crypto_helpers.c
INCLUDES_PATH += $(BOLOS_SDK)/lib_standard_app
Expand Down
1 change: 0 additions & 1 deletion PLUGIN_SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ https://docs.uniswap.org/contracts/universal-router/technical-reference#command-
| V3_SWAP_EXACT_OUT |
| WRAP_ETH |
| UNWRAP_ETH |
| PERMIT2_TRANSFER_FROM |
| PERMIT2_PERMIT_BATCH |
| PERMIT2_TRANSFER_FROM_BATCH |
| PERMIT2_PERMIT |
Expand Down
5 changes: 0 additions & 5 deletions src/check_tx_content.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,5 @@ bool check_tx_content(const txContent_t *tx_content) {
ret = false;
}

if (tx_content->value.length != 0) {
PRINTF("Error: no native eth payment for Uniswap smart contract\n");
ret = false;
}

return ret;
}
128 changes: 41 additions & 87 deletions src/handle_finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,8 @@
#include "weth_token.h"
#include "uniswap_contract_helpers.h"

static bool inferior_or_equal(const uint8_t a[PARAMETER_LENGTH],
const uint8_t b[PARAMETER_LENGTH]) {
return (memcmp(a, b, PARAMETER_LENGTH) <= 0);
}

static bool superior_or_equal(const uint8_t a[PARAMETER_LENGTH],
const uint8_t b[PARAMETER_LENGTH]) {
return (memcmp(a, b, PARAMETER_LENGTH) >= 0);
}

static bool equal(const uint8_t a[PARAMETER_LENGTH], const uint8_t b[PARAMETER_LENGTH]) {
return (memcmp(a, b, PARAMETER_LENGTH) == 0);
static bool superior(const uint8_t a[PARAMETER_LENGTH], const uint8_t b[PARAMETER_LENGTH]) {
return (memcmp(a, b, PARAMETER_LENGTH) > 0);
}

#define PRINT_PARAMETER(title, parameter) \
Expand All @@ -25,71 +15,6 @@ static bool equal(const uint8_t a[PARAMETER_LENGTH], const uint8_t b[PARAMETER_L
PRINTF("\n"); \
} while (0);

/* Table of allowed WRAP / UNWRAP values
* -------------------------------------------------------------------------------------------------
* | WRAP / UNWRAP compared to amount: | INFERIOR | EQUAL | SUPERIOR |
* -------------------------------------------------------------------------------------------------
* | EXACT_IN: | | | |
* | - WRAP: ETH -> WETH -> TOKEN | KO (will fail on chain) | OK | KO (waste) |
* | - UNWRAP: TOKEN -> WETH -> ETH | OK (this is a min) | OK | KO (will fail on chain) |
* -------------------------------------------------------------------------------------------------
* | EXACT_OUT: | | | |
* | - WRAP: ETH -> WETH -> TOKEN | KO (will fail on chain) | OK | OK (but sweep needed!) |
* | - UNWRAP: TOKEN -> WETH -> ETH | OK (this is a min) | OK | KO (will fail on chain) |
* -------------------------------------------------------------------------------------------------
*/
static bool valid_wrap_unwrap_amounts(const context_t *context) {
bool sweep_expected = false;
if (context->swap_type == EXACT_IN) {
if (context->input.asset_type == ETH) {
if (!equal(context->input.u.wrap_unwrap_amount, context->input.amount)) {
PRINTF("Error: wrap amount is not equal to input\n");
PRINT_PARAMETER("context->input.u.wrap_unwrap_amount",
context->input.u.wrap_unwrap_amount);
PRINT_PARAMETER("context->input.amount", context->input.amount);
return false;
}
} else if (context->output.asset_type == ETH) {
if (!inferior_or_equal(context->output.u.wrap_unwrap_amount, context->output.amount)) {
PRINTF("Error: unwrap amount is not inferior_or_equal to output\n");
PRINT_PARAMETER("context->output.u.wrap_unwrap_amount",
context->output.u.wrap_unwrap_amount);
PRINT_PARAMETER("context->output.amount", context->output.amount);
return false;
}
}
} else {
if (context->input.asset_type == ETH) {
sweep_expected = true;
if (!superior_or_equal(context->input.u.wrap_unwrap_amount, context->input.amount)) {
PRINTF("Error: wrap amount is not superior_or_equal to input\n");
PRINT_PARAMETER("context->input.u.wrap_unwrap_amount",
context->input.u.wrap_unwrap_amount);
PRINT_PARAMETER("context->input.amount", context->input.amount);
return false;
}
} else if (context->output.asset_type == ETH) {
if (!inferior_or_equal(context->output.u.wrap_unwrap_amount, context->output.amount)) {
PRINTF("Error: unwrap amount is not inferior_or_equal to output\n");
PRINT_PARAMETER("context->output.u.wrap_unwrap_amount",
context->output.u.wrap_unwrap_amount);
PRINT_PARAMETER("context->output.amount", context->output.amount);
return false;
}
}
}

if (context->sweep_received && !sweep_expected) {
PRINTF("Error: sweep received out of context\n");
return false;
} else if (!context->sweep_received && sweep_expected) {
PRINTF("Error: missing sweep\n");
return false;
}

return true;
}

// Resolve token if possible, request otherwise
static bool resolve_asset(io_data_t *io_data) {
if (io_data->asset_type == ETH) {
Expand Down Expand Up @@ -154,11 +79,11 @@ void handle_finalize(ethPluginFinalize_t *msg) {
}

// This sweep was not just a sweep, it was the main uwrap
if (context->sweep_received && context->output.asset_type == WETH) {
if (context->unwrap_sweep_received && context->output.asset_type == WETH) {
PRINTF("Sweep is actually the main unwrap\n");
context->output.asset_type = ETH;
memset(context->output.u.wrap_unwrap_amount, 0, PARAMETER_LENGTH);
context->sweep_received = false;
context->unwrap_sweep_received = false;
}

if (context->intermediate.intermediate_status != UNUSED) {
Expand All @@ -167,16 +92,45 @@ void handle_finalize(ethPluginFinalize_t *msg) {
return;
}

if (!valid_wrap_unwrap_amounts(context)) {
PRINTF("Error: valid_wrap_unwrap_amounts failed\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
if (msg->pluginSharedRO->txContent->value.length != 0) {
if (context->input.asset_type != ETH) {
PRINTF("Error: no native eth payment for token swap\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
} else if (msg->pluginSharedRO->txContent->value.length > 32) {
PRINTF("Error: invalid value length\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
} else {
uint8_t native_value[PARAMETER_LENGTH];
memset(native_value, 0, PARAMETER_LENGTH);
memmove(
native_value + (PARAMETER_LENGTH - msg->pluginSharedRO->txContent->value.length),
msg->pluginSharedRO->txContent->value.value,
msg->pluginSharedRO->txContent->value.length);
if (superior(native_value, context->input.amount)) {
PRINTF("Using native payment value instead\n");
memmove(context->input.amount, native_value, PARAMETER_LENGTH);
PRINTF("New in value %.*H\n", PARAMETER_LENGTH, context->input.amount);
}
}
}

if (!valid_wrap_unwrap_amounts(context)) {
PRINTF("Error: valid_wrap_unwrap_amounts failed\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
if (context->output.asset_type != ETH) {
if (context->sweep_received) {
PRINTF("Displaying sweep amount as output\n");
PRINTF("context->output.amount %.*H\n", PARAMETER_LENGTH, context->output.amount);
PRINTF("context->sweep_amount %.*H\n", PARAMETER_LENGTH, context->sweep_amount);
memmove(context->output.amount, context->sweep_amount, PARAMETER_LENGTH);
}
} else {
if (context->sweep_received) {
PRINTF("Using sweep_amount as out output\n");
memmove(context->output.amount, context->sweep_amount, PARAMETER_LENGTH);
} else if (superior(context->output.u.wrap_unwrap_amount, context->output.amount)) {
PRINTF("Using unwrap amount as out output\n");
memmove(context->output.amount, context->output.u.wrap_unwrap_amount, PARAMETER_LENGTH);
}
}

if (!is_sender_address(context->recipient, context->own_address)) {
Expand Down
Loading

0 comments on commit d26bee7

Please sign in to comment.