Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,22 @@ bool check_name(const uint8_t *name, uint16_t len) {
}
return true;
}

/**
* @brief Checks if a string contains only displayable ASCII characters.
*
* This function determines if all characters in the provided string are within the
* range of displayable ASCII characters (from 0x20 to 0x7E).
*
* @param str A pointer to the string to be checked.
* @param len The length of the string to be checked.
*/

bool is_displayable_ascii(const char *str, size_t len) {
for (size_t i = 0; i < len; i++) {
if (str[i] < 0x20 || str[i] > 0x7E) {
return false;
}
}
return true;
}
1 change: 1 addition & 0 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
void buf_shrink_expand(const uint8_t *src, size_t src_size, uint8_t *dst, size_t dst_size);
void str_cpy_explicit_trunc(const char *src, size_t src_size, char *dst, size_t dst_size);
bool check_name(const uint8_t *name, uint16_t len);
bool is_displayable_ascii(const char *str, size_t len);
97 changes: 89 additions & 8 deletions src_plugins/erc20/erc20_plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
#include "shared_context.h"
#include "plugin_utils.h"
#include "common_utils.h"
#include "format.h"
#include "utils.h"

typedef enum { ERC20_TRANSFER = 0, ERC20_APPROVE } erc20Selector_t;

#define MAX_CONTRACT_NAME_LEN 15
#define MAX_EXTRA_DATA_SLOTS 2

typedef struct erc20_parameters_t {
uint8_t selectorIndex;
Expand All @@ -16,13 +19,19 @@
char ticker[MAX_TICKER_LEN];
uint8_t decimals;
char contract_name[MAX_CONTRACT_NAME_LEN];
char extra_data[MAX_EXTRA_DATA_SLOTS * 32 + 1];
uint8_t extra_data_len;
} erc20_parameters_t;

void erc20_plugin_call(int message, void *parameters) {
switch (message) {
case ETH_PLUGIN_INIT_CONTRACT: {
ethPluginInitContract_t *msg = (ethPluginInitContract_t *) parameters;
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;

memset(context->extra_data, 0, sizeof(context->extra_data));
context->extra_data_len = 0;

// enforce that ETH amount should be 0
if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)) {
PRINTF("Err: Transaction amount is not 0\n");
Expand Down Expand Up @@ -63,8 +72,18 @@
msg->result = ETH_PLUGIN_RESULT_OK;
break;
default:
PRINTF("Unhandled parameter offset\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
if (msg->parameterOffset <= 4 + 32 + MAX_EXTRA_DATA_SLOTS * 32) {
// store extra data for possible later use
size_t extra_data_offset = msg->parameterOffset - (4 + 32 + 32);
memmove(context->extra_data + extra_data_offset, msg->parameter, 32);
context->extra_data[extra_data_offset + 32] = '\0';
context->extra_data_len += 32;
msg->result = ETH_PLUGIN_RESULT_OK;
} else {
PRINTF("Extra data too long to buffer\n");
context->extra_data_len = 0;
msg->result = ETH_PLUGIN_RESULT_ERROR;
}
break;
}
} break;
Expand All @@ -73,15 +92,15 @@
ethPluginFinalize_t *msg = (ethPluginFinalize_t *) parameters;
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;
PRINTF("erc20 plugin finalize\n");
if (context->selectorIndex == ERC20_TRANSFER) {
if (context->selectorIndex == ERC20_TRANSFER & context->extra_data_len == 0) {
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
msg->amount = context->amount;
msg->address = context->destinationAddress;
msg->uiType = ETH_UI_TYPE_AMOUNT_ADDRESS;
msg->result = ETH_PLUGIN_RESULT_OK;
} else if (context->selectorIndex == ERC20_APPROVE) {
} else {
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
msg->numScreens = 2;
msg->numScreens = (context->extra_data_len == 0 ? 2 : 3);
msg->uiType = ETH_UI_TYPE_GENERIC;
msg->result = ETH_PLUGIN_RESULT_OK;
}
Expand All @@ -104,45 +123,107 @@

case ETH_PLUGIN_QUERY_CONTRACT_ID: {
ethQueryContractID_t *msg = (ethQueryContractID_t *) parameters;
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;

strlcpy(msg->name, "ERC20 token", msg->nameLength);
strlcpy(msg->version, "Approve", msg->versionLength);

if (context->selectorIndex == ERC20_TRANSFER) {
strlcpy(msg->version, "Send", msg->versionLength);
} else {
strlcpy(msg->version, "Approve", msg->versionLength);
}
msg->result = ETH_PLUGIN_RESULT_OK;
} break;

case ETH_PLUGIN_QUERY_CONTRACT_UI: {
ethQueryContractUI_t *msg = (ethQueryContractUI_t *) parameters;
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;
switch (msg->screenIndex) {
case 0:
strlcpy(msg->title, "Amount", msg->titleLength);
if (context->selectorIndex == ERC20_TRANSFER) {
strlcpy(msg->title, "Send", msg->titleLength);
} else {
strlcpy(msg->title, "Approve", msg->titleLength);
}
if (ismaxint(context->amount, sizeof(context->amount))) {
strlcpy(msg->msg, "Unlimited ", msg->msgLength);
strlcat(msg->msg, context->ticker, msg->msgLength);
} else {
if (!amountToString(context->amount,
sizeof(context->amount),
context->decimals,
context->ticker,
msg->msg,
msg->msgLength)) {
msg->result = ETH_PLUGIN_RESULT_ERROR;
break;
}
}
msg->result = ETH_PLUGIN_RESULT_OK;
break;
case 1:
strlcpy(msg->title, "Approve to", msg->titleLength);
if (context->selectorIndex == ERC20_TRANSFER) {
strlcpy(msg->title, "To", msg->titleLength);
} else {
strlcpy(msg->title, "Approve to", msg->titleLength);
}

if (!getEthDisplayableAddress(context->destinationAddress,
msg->msg,
msg->msgLength,
chainConfig->chainId)) {
msg->result = ETH_PLUGIN_RESULT_ERROR;
}
msg->result = ETH_PLUGIN_RESULT_OK;
break;
case 2: {
uint8_t extra_data_len = strnlen(context->extra_data, context->extra_data_len);

PRINTF("Extra Data Length %d\n", extra_data_len);
PRINTF("Message Length %d\n", msg->msgLength);

if (extra_data_len == 0) {
// should not happen
msg->result = ETH_PLUGIN_RESULT_ERROR;
break;
}

strlcpy(msg->title, "Extra Data", msg->titleLength);

if (is_displayable_ascii(context->extra_data, extra_data_len)) {
// display as string
PRINTF("Display as ASCII string\n");

if (extra_data_len >= msg->msgLength) {
// truncate
extra_data_len = msg->msgLength - 1;
context->extra_data[extra_data_len] = '\0';
}
strlcpy(msg->msg, context->extra_data, msg->msgLength);
} else {
// display as hex
PRINTF("Display as Hex string\n");

if (extra_data_len * 2 + 3 > msg->msgLength) {
// truncate
extra_data_len = (msg->msgLength - 3) / 2;
}
msg->msg[0] = '0';
msg->msg[1] = 'x';
if (format_hex((const uint8_t *) context->extra_data,
extra_data_len,
msg->msg + 2,
msg->msgLength - 2) < 0) {
msg->result = ETH_PLUGIN_RESULT_ERROR;
break;
}
}
msg->result = ETH_PLUGIN_RESULT_OK;
break;
}

default:
break;

Check notice

Code scanning / CodeQL

Long switch case Note

Switch has at least one case that is too long:
2 (45 lines)
.
}
} break;

Expand Down
Loading