Skip to content

Commit

Permalink
Merge pull request #664 from LedgerHQ/fbe/allow_thorswap_erc20_tokens
Browse files Browse the repository at this point in the history
When swapping ERC20 tokens with thorswap, ensure amount is 0
  • Loading branch information
fbeutin-ledger authored Oct 11, 2024
2 parents 70cedac + f115468 commit 1731c5f
Showing 1 changed file with 68 additions and 45 deletions.
113 changes: 68 additions & 45 deletions src/handle_swap_sign_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ bool copy_transaction_parameters(create_transaction_parameters_t* sign_transacti
// We need this "trick" as the input data position can overlap with app-ethereum globals
txStringProperties_t stack_data;
uint8_t destination_address_extra_data[CX_SHA256_SIZE + 1];
uint8_t swap_crosschain_hash[sizeof(G_swap_crosschain_hash)];
swap_mode_t swap_mode;

memset(&stack_data, 0, sizeof(stack_data));
memset(destination_address_extra_data, 0, sizeof(destination_address_extra_data));
explicit_bzero(&stack_data, sizeof(stack_data));
explicit_bzero(destination_address_extra_data, sizeof(destination_address_extra_data));
explicit_bzero(swap_crosschain_hash, sizeof(swap_crosschain_hash));

// Set destination address
strlcpy(stack_data.toAddress,
sign_transaction_params->destination_address,
sizeof(stack_data.toAddress));
Expand All @@ -50,81 +54,100 @@ bool copy_transaction_parameters(create_transaction_parameters_t* sign_transacti
(sign_transaction_params->fee_amount_length > 8)) {
return false;
}
PRINTF("Expecting destination_address %s\n", stack_data.toAddress);

if (sign_transaction_params->destination_address_extra_id != NULL) {
memcpy(destination_address_extra_data,
sign_transaction_params->destination_address_extra_id,
sizeof(destination_address_extra_data));
}

char ticker[MAX_TICKER_LEN];
uint8_t decimals;
// if destination_address_extra_id is given, we use the first byte to determine if we use the
// normal swap protocol, or the one for cross-chain swaps
switch (destination_address_extra_data[0]) {
case EXTRA_ID_TYPE_NATIVE:
// we don't use the payin_extra_id field in this mode
swap_mode = SWAP_MODE_STANDARD;
PRINTF("Standard swap\n");
break;
case EXTRA_ID_TYPE_EVM_CALLDATA:
swap_mode = SWAP_MODE_CROSSCHAIN_PENDING_CHECK;

memcpy(swap_crosschain_hash,
destination_address_extra_data + 1,
sizeof(swap_crosschain_hash));

PRINTF("Crosschain swap with hash: %.*H\n", CX_SHA256_SIZE, swap_crosschain_hash);
break;
default:
// We can't return errors from here, we remember that we have an issue to report later
PRINTF("Invalid or unknown swap protocol\n");
swap_mode = SWAP_MODE_ERROR;
}

char asset_ticker[MAX_TICKER_LEN];
uint8_t asset_decimals;
uint64_t chain_id = 0;

if (!parse_swap_config(sign_transaction_params->coin_configuration,
sign_transaction_params->coin_configuration_length,
ticker,
&decimals,
asset_ticker,
&asset_decimals,
&chain_id)) {
PRINTF("Error while parsing config\n");
return false;
}
if (!amountToString(sign_transaction_params->amount,
sign_transaction_params->amount_length,
decimals,
ticker,
stack_data.fullAmount,
sizeof(stack_data.fullAmount))) {
return false;
}

// fallback mechanism in the absence of chain ID in swap config
if (chain_id == 0) {
chain_id = config->chainId;
}
// If the amount is a fee, its value is nominated in ETH even if we're doing an ERC20 swap
strlcpy(ticker, get_displayable_ticker(&chain_id, config), sizeof(ticker));
decimals = WEI_TO_ETHER;
PRINTF("chain_id = %d\n", (uint32_t) chain_id);

// If the amount is a fee, its value is nominated in NATIVE even if we're doing an ERC20 swap
const char* native_ticker = get_displayable_ticker(&chain_id, config);
uint8_t native_decimals = WEI_TO_ETHER;
if (!amountToString(sign_transaction_params->fee_amount,
sign_transaction_params->fee_amount_length,
decimals,
ticker,
native_decimals,
native_ticker,
stack_data.maxFee,
sizeof(stack_data.maxFee))) {
return false;
}
PRINTF("Expecting fees %s\n", stack_data.maxFee);

if (swap_mode == SWAP_MODE_CROSSCHAIN_PENDING_CHECK &&
strcmp(native_ticker, asset_ticker) != 0) {
// Special case: crosschain swap of non native assets (tokens)
uint8_t zero_amount = 0;
if (!amountToString(&zero_amount,
1,
native_decimals,
native_ticker,
stack_data.fullAmount,
sizeof(stack_data.fullAmount))) {
return false;
}
} else {
if (!amountToString(sign_transaction_params->amount,
sign_transaction_params->amount_length,
asset_decimals,
asset_ticker,
stack_data.fullAmount,
sizeof(stack_data.fullAmount))) {
return false;
}
}
PRINTF("Expecting amount %s\n", stack_data.fullAmount);

// Full reset the global variables
os_explicit_zero_BSS_segment();
// Keep the address at which we'll reply the signing status
G_swap_sign_return_value_address = &sign_transaction_params->result;
// Commit the values read from exchange to the clean global space

// if destination_address_extra_id is given, we use the first byte to determine if we use the
// normal swap protocol, or the one for cross-chain swaps
switch (destination_address_extra_data[0]) {
case EXTRA_ID_TYPE_NATIVE:
G_swap_mode = SWAP_MODE_STANDARD;
PRINTF("Standard swap\n");

// we don't use the payin_extra_id field in this mode
explicit_bzero(G_swap_crosschain_hash, sizeof(G_swap_crosschain_hash));
break;
case EXTRA_ID_TYPE_EVM_CALLDATA:
G_swap_mode = SWAP_MODE_CROSSCHAIN_PENDING_CHECK;

memcpy(G_swap_crosschain_hash,
destination_address_extra_data + 1,
sizeof(G_swap_crosschain_hash));

PRINTF("Crosschain swap with hash: %.*H\n", CX_SHA256_SIZE, G_swap_crosschain_hash);
break;
default:
// We can't return errors from here, we remember that we have an issue to report later
PRINTF("Invalid or unknown swap protocol\n");
G_swap_mode = SWAP_MODE_ERROR;
}

G_swap_mode = swap_mode;
memcpy(G_swap_crosschain_hash, swap_crosschain_hash, sizeof(G_swap_crosschain_hash));
memcpy(&strings.common, &stack_data, sizeof(stack_data));
return true;
}
Expand Down

0 comments on commit 1731c5f

Please sign in to comment.