* First draft for erc721 token allowance * Split ui and provide parameters into their own files * Print txtype when not supported * fix compilation for erc721 * Use pluginType * Add debug statement in compound plugin * add debug error msg in plugin error * Add parameter parsing for all methods * Remove debug logs * Add SET_APPROVAL_FOR_ALL; Add correct parsing method on contract init * Add dst_size parameter to copy functions * Add query contract id code * format * Add UIs * update ethapp.asc * Change setExternalPlugin to setPlugin; Add support for ERC721 * clang-format * Fix typo Unconsistent -> Inconsistent * Add support for 721; use extraInfo * Add extraInfo to ethpluginQueryConractUI * Rename extraInfo to item * Add txFromEtherscan to tests * Add nft key and temp padding * Remove comments around HAVE_BYPASS_SIGNATURES * Rename TESTING_KEY to NFT_TESTING_KEY * Add comments regarding value of queryContractUI->item * Fix comment regarding method selector * Rename provideToken to provideInfo; Update plugin doc * fix caps of eth_plugin_prepare_provide_info * fix caps of handle_provide_info * Use verificationFn insead of hardcoded cx_ecdsa_verify * Add comments about nftInfo_t and tokenDefinition_t * Add erc721 test * Remove comment from plugin interface version * Fix network_ticker duplicate * Add setPlugin and provideNFTInfo to doc.asc * Add back setExternalPlugin; implement new setPlugin * Update plugin sdk * Call setPlugin instead of setExternalPlugin * setPlugin work without checking sig * Remove printf of displayed fees * Add working 721 test * Finalize ERC721 and add simple test * Display NFT address on set approval and operator * Support set approval for all for erc721 * Finish UI for set approval for all erc721 * Move copy_parameter and copy_address to eth_plugin_internal; Add tests for erc721 * update plugin sdk * Add erc1155 plugin and 1155 tests placeholder * Add restriction for AWS key and setPlugin * Add NOT_OLD_INTERNAL variant; Add erc_1155_plugin_call * Fixed compilation warnings (function pointer casting) Co-authored-by: pscott <scott.piriou@ledger.fr>
212 lines
7.0 KiB
C
212 lines
7.0 KiB
C
#include "shared_context.h"
|
|
#include "apdu_constants.h"
|
|
#include "ui_flow.h"
|
|
#include "tokens.h"
|
|
|
|
#ifdef HAVE_CONTRACT_NAME_IN_DESCRIPTOR
|
|
|
|
void handleProvideErc20TokenInformation(uint8_t p1,
|
|
uint8_t p2,
|
|
uint8_t *workBuffer,
|
|
uint16_t dataLength,
|
|
unsigned int *flags,
|
|
unsigned int *tx) {
|
|
UNUSED(p1);
|
|
UNUSED(p2);
|
|
UNUSED(flags);
|
|
uint32_t offset = 0;
|
|
uint8_t tickerLength, contractNameLength;
|
|
uint32_t chainId;
|
|
uint8_t hash[INT256_LENGTH];
|
|
cx_sha256_t sha256;
|
|
cx_ecfp_public_key_t tokenKey;
|
|
|
|
cx_sha256_init(&sha256);
|
|
|
|
tmpCtx.transactionContext.currentItemIndex =
|
|
(tmpCtx.transactionContext.currentItemIndex + 1) % MAX_ITEMS;
|
|
tokenDefinition_t *token =
|
|
&tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentItemIndex];
|
|
|
|
if (dataLength < 1) {
|
|
THROW(0x6A80);
|
|
}
|
|
tickerLength = workBuffer[offset++];
|
|
dataLength--;
|
|
if ((tickerLength + 2) >= sizeof(token->ticker)) { // +2 because ' \0' is appended to ticker
|
|
THROW(0x6A80);
|
|
}
|
|
if (dataLength < tickerLength + 1) {
|
|
THROW(0x6A80);
|
|
}
|
|
cx_hash((cx_hash_t *) &sha256, 0, workBuffer + offset, tickerLength, NULL, 0);
|
|
memmove(token->ticker, workBuffer + offset, tickerLength);
|
|
token->ticker[tickerLength] = ' ';
|
|
token->ticker[tickerLength + 1] = '\0';
|
|
offset += tickerLength;
|
|
dataLength -= tickerLength;
|
|
|
|
contractNameLength = workBuffer[offset++];
|
|
dataLength--;
|
|
if (dataLength < contractNameLength + 20 + 4 + 4) {
|
|
THROW(0x6A80);
|
|
}
|
|
cx_hash((cx_hash_t *) &sha256,
|
|
CX_LAST,
|
|
workBuffer + offset,
|
|
contractNameLength + 20 + 4 + 4,
|
|
hash,
|
|
32);
|
|
memmove(token->contractName,
|
|
workBuffer + offset,
|
|
MIN(contractNameLength, sizeof(token->contractName) - 1));
|
|
token->contractName[MIN(contractNameLength, sizeof(token->contractName) - 1)] = '\0';
|
|
offset += contractNameLength;
|
|
dataLength -= contractNameLength;
|
|
|
|
memmove(token->address, workBuffer + offset, 20);
|
|
offset += 20;
|
|
dataLength -= 20;
|
|
token->decimals = U4BE(workBuffer, offset);
|
|
offset += 4;
|
|
dataLength -= 4;
|
|
chainId = U4BE(workBuffer, offset);
|
|
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
|
|
PRINTF("ChainId token mismatch\n");
|
|
THROW(0x6A80);
|
|
}
|
|
offset += 4;
|
|
dataLength -= 4;
|
|
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
|
LEDGER_SIGNATURE_PUBLIC_KEY,
|
|
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
|
&tokenKey);
|
|
if (!cx_ecdsa_verify(&tokenKey,
|
|
CX_LAST,
|
|
CX_SHA256,
|
|
hash,
|
|
32,
|
|
workBuffer + offset,
|
|
dataLength)) {
|
|
#ifndef HAVE_BYPASS_SIGNATURES
|
|
PRINTF("Invalid token signature\n");
|
|
THROW(0x6A80);
|
|
#endif
|
|
}
|
|
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentItemIndex] = 1;
|
|
THROW(0x9000);
|
|
}
|
|
|
|
#else
|
|
|
|
void handleProvideErc20TokenInformation(uint8_t p1,
|
|
uint8_t p2,
|
|
uint8_t *workBuffer,
|
|
uint16_t dataLength,
|
|
unsigned int *flags,
|
|
__attribute__((unused)) unsigned int *tx) {
|
|
UNUSED(p1);
|
|
UNUSED(p2);
|
|
UNUSED(flags);
|
|
uint32_t offset = 0;
|
|
uint8_t tickerLength;
|
|
uint32_t chainId;
|
|
uint8_t hash[INT256_LENGTH];
|
|
cx_ecfp_public_key_t tokenKey;
|
|
|
|
tmpCtx.transactionContext.currentItemIndex =
|
|
(tmpCtx.transactionContext.currentItemIndex + 1) % MAX_ITEMS;
|
|
tokenDefinition_t *token =
|
|
&tmpCtx.transactionContext.extraInfo[tmpCtx.transactionContext.currentItemIndex].token;
|
|
|
|
PRINTF("Provisioning currentItemIndex %d\n", tmpCtx.transactionContext.currentItemIndex);
|
|
|
|
if (dataLength < 1) {
|
|
THROW(0x6A80);
|
|
}
|
|
tickerLength = workBuffer[offset++];
|
|
dataLength--;
|
|
if ((tickerLength + 1) >= sizeof(token->ticker)) {
|
|
THROW(0x6A80);
|
|
}
|
|
if (dataLength < tickerLength + 20 + 4 + 4) {
|
|
THROW(0x6A80);
|
|
}
|
|
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
|
|
memmove(token->ticker, workBuffer + offset, tickerLength);
|
|
token->ticker[tickerLength] = ' ';
|
|
token->ticker[tickerLength + 1] = '\0';
|
|
offset += tickerLength;
|
|
dataLength -= tickerLength;
|
|
memmove(token->address, workBuffer + offset, 20);
|
|
offset += 20;
|
|
dataLength -= 20;
|
|
token->decimals = U4BE(workBuffer, offset);
|
|
offset += 4;
|
|
dataLength -= 4;
|
|
chainId = U4BE(workBuffer, offset);
|
|
if ((chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) && (chainConfig->chainId != chainId)) {
|
|
PRINTF("ChainId token mismatch: %d vs %d\n", chainConfig->chainId, chainId);
|
|
THROW(0x6A80);
|
|
}
|
|
offset += 4;
|
|
dataLength -= 4;
|
|
|
|
#ifdef HAVE_TOKENS_EXTRA_LIST
|
|
tokenDefinition_t *currentToken = NULL;
|
|
uint32_t index;
|
|
for (index = 0; index < NUM_TOKENS_EXTRA; index++) {
|
|
currentToken = (tokenDefinition_t *) PIC(&TOKENS_EXTRA[index]);
|
|
if (memcmp(currentToken->address, token->address, 20) == 0) {
|
|
strcpy((char *) token->ticker, (char *) currentToken->ticker);
|
|
token->decimals = currentToken->decimals;
|
|
break;
|
|
}
|
|
}
|
|
if (index < NUM_TOKENS_EXTRA) {
|
|
PRINTF("Descriptor whitelisted\n");
|
|
} else {
|
|
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
|
LEDGER_SIGNATURE_PUBLIC_KEY,
|
|
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
|
&tokenKey);
|
|
if (!cx_ecdsa_verify(&tokenKey,
|
|
CX_LAST,
|
|
CX_SHA256,
|
|
hash,
|
|
32,
|
|
workBuffer + offset,
|
|
dataLength)) {
|
|
#ifndef HAVE_BYPASS_SIGNATURES
|
|
PRINTF("Invalid token signature\n");
|
|
THROW(0x6A80);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
|
LEDGER_SIGNATURE_PUBLIC_KEY,
|
|
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
|
|
&tokenKey);
|
|
if (!cx_ecdsa_verify(&tokenKey,
|
|
CX_LAST,
|
|
CX_SHA256,
|
|
hash,
|
|
32,
|
|
workBuffer + offset,
|
|
dataLength)) {
|
|
#ifndef HAVE_BYPASS_SIGNATURES
|
|
PRINTF("Invalid token signature\n");
|
|
THROW(0x6A80);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentItemIndex] = 1;
|
|
THROW(0x9000);
|
|
}
|
|
|
|
#endif
|