Fix nft transactions (#229)
* Removed pluginType "hack" * Fix some ERC 721 & 1155 function signature hashes * Fix UI for ERC721 operations * Explicit Batch Transfer UI with ERC1155 * Unified some ERC721 & 1155 non-static functions naming * Fix UI for ERC1155 operations * Added missing pin-lock check when signing transactions * Fix the shell script that builds the elf files for testing * Add tests dependency ethers * Removed the space in the test filename * Tests build script refactoring * Now works when called from anywhere (not just the script's directory) * Now handles LNS & LNX builds together (less duplicated code) * Temporarily disable Nano X tests Until Zemu supports Nano X 2.0 SDK * Tests now start with blind signing disabled Makes it closer to reality & very few of them requires it * Update to the latest sdk version * make eth_plugin_perform_init() readable Introduce 2 functions. * Now properly parses the apdu and displays the total quantity of NFT IDs transferred in ERC1155 batch transfer * Add NFT prod public keys * Added extra checks for the chain ID handling Following the security review * NFTs now only supported by LNS * Version bump Co-authored-by: Alexandre Paillier <alexandre.paillier@ledger.fr> Co-authored-by: greenknot <greenknot@users.noreply.github.com>
This commit is contained in:
@@ -72,69 +72,77 @@ void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI,
|
||||
queryContractUI->msgLength = msgLength;
|
||||
}
|
||||
|
||||
static void eth_plugin_perform_init_default(uint8_t *contractAddress,
|
||||
ethPluginInitContract_t *init) {
|
||||
// check if the registered external plugin matches the TX contract address / selector
|
||||
if (memcmp(contractAddress,
|
||||
dataContext.tokenContext.contractAddress,
|
||||
sizeof(dataContext.tokenContext.contractAddress)) != 0) {
|
||||
PRINTF("Got contract: %.*H\n", ADDRESS_LENGTH, contractAddress);
|
||||
PRINTF("Expected contract: %.*H\n",
|
||||
ADDRESS_LENGTH,
|
||||
dataContext.tokenContext.contractAddress);
|
||||
os_sched_exit(0);
|
||||
}
|
||||
if (memcmp(init->selector,
|
||||
dataContext.tokenContext.methodSelector,
|
||||
sizeof(dataContext.tokenContext.methodSelector)) != 0) {
|
||||
PRINTF("Got selector: %.*H\n", SELECTOR_SIZE, init->selector);
|
||||
PRINTF("Expected selector: %.*H\n", SELECTOR_SIZE, dataContext.tokenContext.methodSelector);
|
||||
os_sched_exit(0);
|
||||
}
|
||||
PRINTF("Plugin will be used\n");
|
||||
dataContext.tokenContext.pluginStatus = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
|
||||
static bool eth_plugin_perform_init_old_internal(uint8_t *contractAddress,
|
||||
ethPluginInitContract_t *init) {
|
||||
uint8_t i, j;
|
||||
const uint8_t **selectors;
|
||||
|
||||
// Search internal plugin list
|
||||
for (i = 0;; i++) {
|
||||
selectors = (const uint8_t **) PIC(INTERNAL_ETH_PLUGINS[i].selectors);
|
||||
if (selectors == NULL) {
|
||||
break;
|
||||
}
|
||||
for (j = 0; ((j < INTERNAL_ETH_PLUGINS[i].num_selectors) && (contractAddress != NULL));
|
||||
j++) {
|
||||
if (memcmp(init->selector, (const void *) PIC(selectors[j]), SELECTOR_SIZE) == 0) {
|
||||
if ((INTERNAL_ETH_PLUGINS[i].availableCheck == NULL) ||
|
||||
((PluginAvailableCheck) PIC(INTERNAL_ETH_PLUGINS[i].availableCheck))()) {
|
||||
strlcpy(dataContext.tokenContext.pluginName,
|
||||
INTERNAL_ETH_PLUGINS[i].alias,
|
||||
PLUGIN_ID_LENGTH);
|
||||
dataContext.tokenContext.pluginStatus = ETH_PLUGIN_RESULT_OK;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
eth_plugin_result_t eth_plugin_perform_init(uint8_t *contractAddress,
|
||||
ethPluginInitContract_t *init) {
|
||||
uint8_t i;
|
||||
const uint8_t **selectors;
|
||||
dataContext.tokenContext.pluginStatus = ETH_PLUGIN_RESULT_UNAVAILABLE;
|
||||
|
||||
PRINTF("Selector %.*H\n", 4, init->selector);
|
||||
switch (pluginType) {
|
||||
case NOT_OLD_INTERNAL:
|
||||
#ifdef HAVE_NFT_SUPPORT
|
||||
case ERC1155:
|
||||
case ERC721:
|
||||
case EXTERNAL: {
|
||||
// check if the registered external plugin matches the TX contract address / selector
|
||||
if (memcmp(contractAddress,
|
||||
dataContext.tokenContext.contractAddress,
|
||||
sizeof(dataContext.tokenContext.contractAddress)) != 0) {
|
||||
PRINTF("Got contract: %.*H\n", ADDRESS_LENGTH, contractAddress);
|
||||
PRINTF("Expected contract: %.*H\n",
|
||||
ADDRESS_LENGTH,
|
||||
dataContext.tokenContext.contractAddress);
|
||||
os_sched_exit(0);
|
||||
}
|
||||
if (memcmp(init->selector,
|
||||
dataContext.tokenContext.methodSelector,
|
||||
sizeof(dataContext.tokenContext.methodSelector)) != 0) {
|
||||
PRINTF("Got selector: %.*H\n", SELECTOR_SIZE, init->selector);
|
||||
PRINTF("Expected selector: %.*H\n",
|
||||
SELECTOR_SIZE,
|
||||
dataContext.tokenContext.methodSelector);
|
||||
os_sched_exit(0);
|
||||
}
|
||||
PRINTF("Plugin will be used\n");
|
||||
// TODO: Add check for chainid.
|
||||
dataContext.tokenContext.pluginStatus = ETH_PLUGIN_RESULT_OK;
|
||||
#endif // HAVE_NFT_SUPPORT
|
||||
case EXTERNAL:
|
||||
eth_plugin_perform_init_default(contractAddress, init);
|
||||
contractAddress = NULL;
|
||||
} break;
|
||||
case OLD_INTERNAL: {
|
||||
// Search internal plugin list
|
||||
for (i = 0;; i++) {
|
||||
uint8_t j;
|
||||
selectors = (const uint8_t **) PIC(INTERNAL_ETH_PLUGINS[i].selectors);
|
||||
if (selectors == NULL) {
|
||||
break;
|
||||
}
|
||||
for (j = 0;
|
||||
((j < INTERNAL_ETH_PLUGINS[i].num_selectors) && (contractAddress != NULL));
|
||||
j++) {
|
||||
if (memcmp(init->selector, (const void *) PIC(selectors[j]), SELECTOR_SIZE) ==
|
||||
0) {
|
||||
if ((INTERNAL_ETH_PLUGINS[i].availableCheck == NULL) ||
|
||||
((PluginAvailableCheck) PIC(
|
||||
INTERNAL_ETH_PLUGINS[i].availableCheck))()) {
|
||||
strlcpy(dataContext.tokenContext.pluginName,
|
||||
INTERNAL_ETH_PLUGINS[i].alias,
|
||||
PLUGIN_ID_LENGTH);
|
||||
dataContext.tokenContext.pluginStatus = ETH_PLUGIN_RESULT_OK;
|
||||
contractAddress = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OLD_INTERNAL:
|
||||
if (eth_plugin_perform_init_old_internal(contractAddress, init)) {
|
||||
contractAddress = NULL;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unsupported pluginType %d\n", pluginType);
|
||||
os_sched_exit(0);
|
||||
@@ -242,8 +250,6 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) {
|
||||
}
|
||||
|
||||
switch (pluginType) {
|
||||
case NOT_OLD_INTERNAL:
|
||||
break;
|
||||
case EXTERNAL: {
|
||||
uint32_t params[3];
|
||||
params[0] = (uint32_t) alias;
|
||||
@@ -262,6 +268,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) {
|
||||
END_TRY;
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_NFT_SUPPORT
|
||||
case ERC721: {
|
||||
erc721_plugin_call(method, parameter);
|
||||
break;
|
||||
@@ -270,6 +277,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) {
|
||||
erc1155_plugin_call(method, parameter);
|
||||
break;
|
||||
}
|
||||
#endif // HAVE_NFT_SUPPORT
|
||||
case OLD_INTERNAL: {
|
||||
// Perform the call
|
||||
for (i = 0;; i++) {
|
||||
|
||||
@@ -513,6 +513,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
tx);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_NFT_SUPPORT
|
||||
case INS_PROVIDE_NFT_INFORMATION:
|
||||
handleProvideNFTInformation(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
@@ -521,6 +522,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
#endif // HAVE_NFT_SUPPORT
|
||||
|
||||
case INS_SET_EXTERNAL_PLUGIN:
|
||||
handleSetExternalPlugin(G_io_apdu_buffer[OFFSET_P1],
|
||||
|
||||
@@ -207,8 +207,7 @@ typedef enum {
|
||||
EXTERNAL, // External plugin, set by setExternalPlugin.
|
||||
ERC721, // Specific ERC721 internal plugin, set by setPlugin.
|
||||
ERC1155, // Specific ERC1155 internal plugin, set by setPlugin
|
||||
OLD_INTERNAL, // Old internal plugin, not set by any command.
|
||||
NOT_OLD_INTERNAL, // Do not treat this tx as an old internal transaction.
|
||||
OLD_INTERNAL // Old internal plugin, not set by any command.
|
||||
} pluginType_t;
|
||||
|
||||
extern pluginType_t pluginType;
|
||||
|
||||
Reference in New Issue
Block a user