From 1b9e575d3ef4de6c7ccbc3f6b0d2964a4133de03 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Tue, 25 Jan 2022 22:50:43 +0100 Subject: [PATCH 01/32] refactor(legacy): Move path constants to crypto.h. --- legacy/firmware/crypto.c | 48 ++++++++++++++---------------- legacy/firmware/crypto.h | 6 ++++ legacy/firmware/fsm_msg_coin.h | 2 +- legacy/firmware/fsm_msg_crypto.h | 20 ++++++------- legacy/firmware/fsm_msg_ethereum.h | 2 +- legacy/firmware/layout2.c | 37 ++++++++++++----------- legacy/firmware/u2f.c | 5 ++-- 7 files changed, 63 insertions(+), 57 deletions(-) diff --git a/legacy/firmware/crypto.c b/legacy/firmware/crypto.c index faca68e9c..ddcfc8444 100644 --- a/legacy/firmware/crypto.c +++ b/legacy/firmware/crypto.c @@ -36,10 +36,6 @@ #include "cash_addr.h" #endif -#define PATH_MAX_ACCOUNT 100 -#define PATH_MAX_CHANGE 1 -#define PATH_MAX_ADDRESS_INDEX 1000000 - uint32_t ser_length(uint32_t len, uint8_t *out) { if (len < 253) { out[0] = len & 0xFF; @@ -508,7 +504,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, bool valid = true; // m/44' : BIP44 Legacy // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 44)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 44)) { if (check_known) { valid = valid && (address_n_count == 5); } else { @@ -520,7 +516,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (!has_multisig); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -528,7 +524,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, return valid; } - if (address_n_count > 0 && address_n[0] == (0x80000000 + 45)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 45)) { if (check_script_type) { valid = valid && has_multisig; } @@ -556,7 +552,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, script_type == InputScriptType_SPENDMULTISIG); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= 1000000); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -566,15 +562,15 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // future. // m/45'/coin_type'/account'/[0-1000000]/change/address_index // m/45'/coin_type/account/[0-1000000]/change/address_index - valid = - valid && check_cointype(coin, 0x80000000 | address_n[1], check_known); + valid = valid && + check_cointype(coin, PATH_HARDENED | address_n[1], check_known); if (check_script_type) { valid = valid && (script_type == InputScriptType_SPENDADDRESS || script_type == InputScriptType_SPENDMULTISIG); } if (check_known) { - valid = valid && - ((address_n[1] & 0x80000000) == (address_n[2] & 0x80000000)); + valid = valid && ((address_n[1] & PATH_HARDENED) == + (address_n[2] & PATH_HARDENED)); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= 1000000); valid = valid && (address_n[4] <= PATH_MAX_CHANGE); @@ -593,7 +589,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m / purpose' / coin_type' / account' / change / address_index // Electrum: // m / purpose' / coin_type' / account' / type' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 48)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 48)) { if (check_known) { valid = valid && (address_n_count == 5 || address_n_count == 6); } else { @@ -608,13 +604,13 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, script_type == InputScriptType_SPENDWITNESS); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); if (address_n_count == 5) { valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); } else if (address_n_count == 6) { - valid = valid && ((address_n[3] & 0x80000000) == 0x80000000); + valid = valid && (address_n[3] & PATH_HARDENED); valid = valid && ((address_n[3] & 0x7fffffff) <= 3); valid = valid && (address_n[4] <= PATH_MAX_CHANGE); valid = valid && (address_n[5] <= PATH_MAX_ADDRESS_INDEX); @@ -627,7 +623,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m/49' : BIP49 SegWit // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 49)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 49)) { valid = valid && coin->has_segwit; if (check_known) { valid = valid && (address_n_count == 5); @@ -639,7 +635,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (script_type == InputScriptType_SPENDP2SHWITNESS); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -649,7 +645,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m/84' : BIP84 Native SegWit // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 84)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 84)) { valid = valid && coin->has_segwit; valid = valid && (coin->bech32_prefix != NULL); if (check_known) { @@ -662,7 +658,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (script_type == InputScriptType_SPENDWITNESS); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -672,7 +668,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // m/86' : BIP86 Taproot // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 86)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 86)) { valid = valid && coin->has_taproot; valid = valid && (coin->bech32_prefix != NULL); if (check_known) { @@ -687,7 +683,7 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, valid = valid && (script_type == InputScriptType_SPENDTAPROOT); } if (check_known) { - valid = valid && ((address_n[2] & 0x80000000) == 0x80000000); + valid = valid && (address_n[2] & PATH_HARDENED); valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); @@ -708,11 +704,11 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // Green Address compatibility pattern. Will be removed in the future. // m / 3' / [1-100]' / [1,4] / address_index - if (address_n_count > 0 && address_n[0] == (0x80000000 + 3)) { + if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 3)) { valid = valid && (coin->coin_type == SLIP44_BITCOIN); if (check_known) { valid = valid && (address_n_count == 4); - valid = valid && ((address_n[1] & 0x80000000) == 0x80000000); + valid = valid && (address_n[1] & PATH_HARDENED); valid = valid && ((address_n[1] & 0x7fffffff) <= 100); valid = valid && (address_n[2] == 1 || address_n[2] == 4); valid = valid && (address_n[3] <= PATH_MAX_ADDRESS_INDEX); @@ -744,13 +740,13 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, } else { valid = valid && (address_n_count >= 2); } - valid = - valid && check_cointype(coin, 0x80000000 | address_n[1], check_known); + valid = valid && + check_cointype(coin, PATH_HARDENED | address_n[1], check_known); if (check_script_type) { valid = valid && (script_type == InputScriptType_SPENDP2SHWITNESS); } if (check_known) { - valid = valid && ((address_n[1] & 0x80000000) == 0); + valid = valid && ((address_n[1] & PATH_HARDENED) == 0); valid = valid && (address_n[2] <= PATH_MAX_ACCOUNT); valid = valid && (address_n[3] <= PATH_MAX_CHANGE); valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); diff --git a/legacy/firmware/crypto.h b/legacy/firmware/crypto.h index 2c26b8905..b8675ccb6 100644 --- a/legacy/firmware/crypto.h +++ b/legacy/firmware/crypto.h @@ -38,6 +38,12 @@ typedef enum _CoinPathCheckLevel { CoinPathCheckLevel_SCRIPT_TYPE = 2, } CoinPathCheckLevel; +#define PATH_HARDENED 0x80000000 +#define PATH_UNHARDEN_MASK 0x7fffffff +#define PATH_MAX_ACCOUNT 100 +#define PATH_MAX_CHANGE 1 +#define PATH_MAX_ADDRESS_INDEX 1000000 + #define ser_length_size(len) ((len) < 253 ? 1 : (len) < 0x10000 ? 3 : 5) uint32_t ser_length(uint32_t len, uint8_t *out); diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index 778805af1..b36cadb53 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -37,7 +37,7 @@ void fsm_msgGetPublicKey(const GetPublicKey *msg) { // derive m/0' to obtain root_fingerprint uint32_t root_fingerprint; - uint32_t path[1] = {0x80000000 | 0}; + uint32_t path[1] = {PATH_HARDENED | 0}; HDNode *node = fsm_getDerivedNode(curve, path, 1, &root_fingerprint); if (!node) return; diff --git a/legacy/firmware/fsm_msg_crypto.h b/legacy/firmware/fsm_msg_crypto.h index da9e76cd4..cae8e2bea 100644 --- a/legacy/firmware/fsm_msg_crypto.h +++ b/legacy/firmware/fsm_msg_crypto.h @@ -93,14 +93,14 @@ void fsm_msgSignIdentity(const SignIdentity *msg) { } uint32_t address_n[5]; - address_n[0] = 0x80000000 | 13; - address_n[1] = 0x80000000 | hash[0] | (hash[1] << 8) | (hash[2] << 16) | + address_n[0] = PATH_HARDENED | 13; + address_n[1] = PATH_HARDENED | hash[0] | (hash[1] << 8) | (hash[2] << 16) | ((uint32_t)hash[3] << 24); - address_n[2] = 0x80000000 | hash[4] | (hash[5] << 8) | (hash[6] << 16) | + address_n[2] = PATH_HARDENED | hash[4] | (hash[5] << 8) | (hash[6] << 16) | ((uint32_t)hash[7] << 24); - address_n[3] = 0x80000000 | hash[8] | (hash[9] << 8) | (hash[10] << 16) | + address_n[3] = PATH_HARDENED | hash[8] | (hash[9] << 8) | (hash[10] << 16) | ((uint32_t)hash[11] << 24); - address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | + address_n[4] = PATH_HARDENED | hash[12] | (hash[13] << 8) | (hash[14] << 16) | ((uint32_t)hash[15] << 24); const char *curve = SECP256K1_NAME; @@ -196,14 +196,14 @@ void fsm_msgGetECDHSessionKey(const GetECDHSessionKey *msg) { } uint32_t address_n[5]; - address_n[0] = 0x80000000 | 17; - address_n[1] = 0x80000000 | hash[0] | (hash[1] << 8) | (hash[2] << 16) | + address_n[0] = PATH_HARDENED | 17; + address_n[1] = PATH_HARDENED | hash[0] | (hash[1] << 8) | (hash[2] << 16) | ((uint32_t)hash[3] << 24); - address_n[2] = 0x80000000 | hash[4] | (hash[5] << 8) | (hash[6] << 16) | + address_n[2] = PATH_HARDENED | hash[4] | (hash[5] << 8) | (hash[6] << 16) | ((uint32_t)hash[7] << 24); - address_n[3] = 0x80000000 | hash[8] | (hash[9] << 8) | (hash[10] << 16) | + address_n[3] = PATH_HARDENED | hash[8] | (hash[9] << 8) | (hash[10] << 16) | ((uint32_t)hash[11] << 24); - address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | + address_n[4] = PATH_HARDENED | hash[12] | (hash[13] << 8) | (hash[14] << 16) | ((uint32_t)hash[15] << 24); const char *curve = SECP256K1_NAME; diff --git a/legacy/firmware/fsm_msg_ethereum.h b/legacy/firmware/fsm_msg_ethereum.h index 43337f92d..3ca3b1070 100644 --- a/legacy/firmware/fsm_msg_ethereum.h +++ b/legacy/firmware/fsm_msg_ethereum.h @@ -110,7 +110,7 @@ void fsm_msgEthereumGetAddress(const EthereumGetAddress *msg) { if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) return; uint32_t slip44 = - (msg->address_n_count > 1) ? (msg->address_n[1] & 0x7fffffff) : 0; + (msg->address_n_count > 1) ? (msg->address_n[1] & PATH_UNHARDEN_MASK) : 0; bool rskip60 = false; uint64_t chain_id = 0; // constants from trezor-common/defs/ethereum/networks.json diff --git a/legacy/firmware/layout2.c b/legacy/firmware/layout2.c index 89daa1a26..adbd22d4f 100644 --- a/legacy/firmware/layout2.c +++ b/legacy/firmware/layout2.c @@ -27,6 +27,7 @@ #include "bignum.h" #include "bitmaps.h" #include "config.h" +#include "crypto.h" #include "gettext.h" #include "layout2.h" #include "memzero.h" @@ -43,10 +44,10 @@ #if !BITCOIN_ONLY static const char *slip44_extras(uint32_t coin_type) { - if ((coin_type & 0x80000000) == 0) { + if ((coin_type & PATH_HARDENED) == 0) { return 0; } - switch (coin_type & 0x7fffffff) { + switch (coin_type & PATH_UNHARDEN_MASK) { case 40: return "EXP"; // Expanse case 43: @@ -82,14 +83,15 @@ static const char *address_n_str(const uint32_t *address_n, // known BIP44/49/84/86 path static char path[100]; if (address_n_count == 5 && - (address_n[0] == (0x80000000 + 44) || address_n[0] == (0x80000000 + 49) || - address_n[0] == (0x80000000 + 84) || - address_n[0] == (0x80000000 + 86)) && - (address_n[1] & 0x80000000) && (address_n[2] & 0x80000000) && + (address_n[0] == (PATH_HARDENED + 44) || + address_n[0] == (PATH_HARDENED + 49) || + address_n[0] == (PATH_HARDENED + 84) || + address_n[0] == (PATH_HARDENED + 86)) && + (address_n[1] & PATH_HARDENED) && (address_n[2] & PATH_HARDENED) && (address_n[3] <= 1) && (address_n[4] <= BIP32_MAX_LAST_ELEMENT)) { - bool taproot = (address_n[0] == (0x80000000 + 86)); - bool native_segwit = (address_n[0] == (0x80000000 + 84)); - bool p2sh_segwit = (address_n[0] == (0x80000000 + 49)); + bool taproot = (address_n[0] == (PATH_HARDENED + 86)); + bool native_segwit = (address_n[0] == (PATH_HARDENED + 84)); + bool p2sh_segwit = (address_n[0] == (PATH_HARDENED + 49)); bool legacy = false; const CoinInfo *coin = coinBySlip44(address_n[1]); const char *abbr = 0; @@ -118,8 +120,8 @@ static const char *address_n_str(const uint32_t *address_n, } } const uint32_t accnum = address_is_account - ? ((address_n[4] & 0x7fffffff) + 1) - : (address_n[2] & 0x7fffffff) + 1; + ? ((address_n[4] & PATH_UNHARDEN_MASK) + 1) + : (address_n[2] & PATH_UNHARDEN_MASK) + 1; if (abbr && accnum < 100) { memzero(path, sizeof(path)); strlcpy(path, abbr, sizeof(path)); @@ -164,11 +166,11 @@ static const char *address_n_str(const uint32_t *address_n, for (int n = (int)address_n_count - 1; n >= 0; n--) { uint32_t i = address_n[n]; - if (i & 0x80000000) { + if (i & PATH_HARDENED) { *c = '\''; c--; } - i = i & 0x7fffffff; + i = i & PATH_UNHARDEN_MASK; do { *c = '0' + (i % 10); c--; @@ -1176,8 +1178,9 @@ void layoutNEMLevy(const NEMMosaicDefinition *definition, uint8_t network) { static inline bool is_slip18(const uint32_t *address_n, size_t address_n_count) { - return address_n_count == 2 && address_n[0] == (0x80000000 + 10018) && - (address_n[1] & 0x80000000) && (address_n[1] & 0x7FFFFFFF) <= 9; + return address_n_count == 2 && address_n[0] == (PATH_HARDENED + 10018) && + (address_n[1] & PATH_HARDENED) && + (address_n[1] & PATH_UNHARDEN_MASK) <= 9; } void layoutCosiCommitSign(const uint32_t *address_n, size_t address_n_count, @@ -1187,10 +1190,10 @@ void layoutCosiCommitSign(const uint32_t *address_n, size_t address_n_count, if (is_slip18(address_n, address_n_count)) { if (final_sign) { strlcpy(desc_buf, _("CoSi sign index #?"), sizeof(desc_buf)); - desc_buf[16] = '0' + (address_n[1] & 0x7FFFFFFF); + desc_buf[16] = '0' + (address_n[1] & PATH_UNHARDEN_MASK); } else { strlcpy(desc_buf, _("CoSi commit index #?"), sizeof(desc_buf)); - desc_buf[18] = '0' + (address_n[1] & 0x7FFFFFFF); + desc_buf[18] = '0' + (address_n[1] & PATH_UNHARDEN_MASK); } desc = desc_buf; } diff --git a/legacy/firmware/u2f.c b/legacy/firmware/u2f.c index 1dbfb7a17..c71c74316 100644 --- a/legacy/firmware/u2f.c +++ b/legacy/firmware/u2f.c @@ -23,6 +23,7 @@ #include "bip32.h" #include "buttons.h" #include "config.h" +#include "crypto.h" #include "curves.h" #include "debug.h" #include "gettext.h" @@ -481,7 +482,7 @@ static const HDNode *generateKeyHandle(const uint8_t app_id[], uint32_t key_path[KEY_PATH_ENTRIES] = {0}; for (uint32_t i = 0; i < KEY_PATH_ENTRIES; i++) { // high bit for hardened keys - key_path[i] = 0x80000000 | random32(); + key_path[i] = PATH_HARDENED | random32(); } // First half of keyhandle is key_path @@ -508,7 +509,7 @@ static const HDNode *validateKeyHandle(const uint8_t app_id[], memcpy(key_path, key_handle, KEY_PATH_LEN); for (unsigned int i = 0; i < KEY_PATH_ENTRIES; i++) { // check high bit for hardened keys - if (!(key_path[i] & 0x80000000)) { + if (!(key_path[i] & PATH_HARDENED)) { return NULL; } } From 054ab486894ff654d2356143d99d39f84648710d Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Wed, 26 Jan 2022 18:45:45 +0100 Subject: [PATCH 02/32] refactor(legacy): Factor out fsm_layoutPathWarning(). --- legacy/firmware/fsm.c | 12 ++++++++++++ legacy/firmware/fsm.h | 2 ++ legacy/firmware/fsm_msg_coin.h | 7 +------ legacy/firmware/signing.c | 7 +------ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/legacy/firmware/fsm.c b/legacy/firmware/fsm.c index 6c022204d..c91908433 100644 --- a/legacy/firmware/fsm.c +++ b/legacy/firmware/fsm.c @@ -370,6 +370,18 @@ void fsm_msgRebootToBootloader(void) { #endif } +bool fsm_layoutPathWarning(void) { + layoutDialogSwipe(&bmp_icon_warning, _("Abort"), _("Continue"), NULL, + _("Wrong address path"), _("for selected coin."), NULL, + _("Continue at your"), _("own risk!"), NULL); + if (!protectButton(ButtonRequestType_ButtonRequest_UnknownDerivationPath, + false)) { + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); + return false; + } + return true; +} + #include "fsm_msg_coin.h" #include "fsm_msg_common.h" #include "fsm_msg_crypto.h" diff --git a/legacy/firmware/fsm.h b/legacy/firmware/fsm.h index 5c43862bd..c22cca9bf 100644 --- a/legacy/firmware/fsm.h +++ b/legacy/firmware/fsm.h @@ -143,4 +143,6 @@ void fsm_msgRebootToBootloader(void); bool fsm_layoutSignMessage(const uint8_t *msg, uint32_t len); bool fsm_layoutVerifyMessage(const uint8_t *msg, uint32_t len); +bool fsm_layoutPathWarning(void); + #endif diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index b36cadb53..71f4afcc3 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -164,12 +164,7 @@ static bool fsm_checkCoinPath(const CoinInfo *coin, InputScriptType script_type, return false; } - layoutDialogSwipe(&bmp_icon_warning, _("Abort"), _("Continue"), NULL, - _("Wrong address path"), _("for selected coin."), NULL, - _("Continue at your"), _("own risk!"), NULL); - if (!protectButton(ButtonRequestType_ButtonRequest_UnknownDerivationPath, - false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); + if (!fsm_layoutPathWarning()) { layoutHome(); return false; } diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index e59052c38..d26ba0ff7 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -763,12 +763,7 @@ static bool derive_node(TxInputType *tinput) { return false; } - layoutDialogSwipe(&bmp_icon_warning, _("Abort"), _("Continue"), NULL, - _("Wrong address path"), _("for selected coin."), NULL, - _("Continue at your"), _("own risk!"), NULL); - if (!protectButton(ButtonRequestType_ButtonRequest_UnknownDerivationPath, - false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); + if (!fsm_layoutPathWarning()) { signing_abort(); return false; } From 0af5cd18c226e5659d6467615dca7cbd879a9f00 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Tue, 25 Jan 2022 22:54:31 +0100 Subject: [PATCH 03/32] feat(legacy): Strict path validation for Ethereum. --- legacy/firmware/.changelog.d/noissue.security | 1 + legacy/firmware/ethereum.c | 49 +++++++++++++++ legacy/firmware/ethereum.h | 4 ++ legacy/firmware/ethereum_networks.h.mako | 35 +++++++++-- legacy/firmware/fsm_msg_ethereum.h | 59 ++++++++++++++++++- 5 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 legacy/firmware/.changelog.d/noissue.security diff --git a/legacy/firmware/.changelog.d/noissue.security b/legacy/firmware/.changelog.d/noissue.security new file mode 100644 index 000000000..71a0f5aa8 --- /dev/null +++ b/legacy/firmware/.changelog.d/noissue.security @@ -0,0 +1 @@ +Strict path validations for altcoins. diff --git a/legacy/firmware/ethereum.c b/legacy/firmware/ethereum.c index 66289f393..0804410d8 100644 --- a/legacy/firmware/ethereum.c +++ b/legacy/firmware/ethereum.c @@ -1040,3 +1040,52 @@ bool ethereum_parse(const char *address, uint8_t pubkeyhash[20]) { } return true; } + +bool ethereum_path_check(uint32_t address_n_count, const uint32_t *address_n, + bool pubkey_export, uint64_t chain) { + bool valid = (address_n_count >= 3); + valid = valid && (address_n[0] == (PATH_HARDENED | 44)); + valid = valid && (address_n[1] & PATH_HARDENED); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + + uint32_t path_slip44 = address_n[1] & PATH_UNHARDEN_MASK; + if (chain == CHAIN_ID_UNKNOWN) { + valid = valid && (is_ethereum_slip44(path_slip44)); + } else { + uint32_t chain_slip44 = ethereum_slip44_by_chain_id(chain); + if (chain_slip44 == SLIP44_UNKNOWN) { + // Allow Ethereum or testnet paths for unknown networks. + valid = valid && (path_slip44 == 60 || path_slip44 == 1); + } else if (chain_slip44 != 60 && chain_slip44 != 1) { + // Allow cross-signing with Ethereum unless it's testnet. + valid = valid && (path_slip44 == chain_slip44 || path_slip44 == 60); + } else { + valid = valid && (path_slip44 == chain_slip44); + } + } + + if (pubkey_export) { + // m/44'/coin_type'/account'/* + return valid; + } + + if (address_n_count == 3) { + // SEP-0005 for non-UTXO-based currencies, defined by Stellar: + // https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md + // m/44'/coin_type'/account' + return valid; + } + + // We believe Ethereum should use the SEP-0005 scheme for everything, because + // it is account-based, rather than UTXO-based. Unfortunately, a lot of + // Ethereum tools (MEW, Metamask) do not use such scheme and set account = 0 + // and then iterate the address index. For compatibility, we allow this scheme + // as well. + // m/44'/coin_type'/account'/change/address_index + valid = valid && (address_n_count == 5); + valid = valid && (address_n[3] <= PATH_MAX_CHANGE); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); + + return valid; +} diff --git a/legacy/firmware/ethereum.h b/legacy/firmware/ethereum.h index feb287925..bae4c56ba 100644 --- a/legacy/firmware/ethereum.h +++ b/legacy/firmware/ethereum.h @@ -25,6 +25,8 @@ #include "bip32.h" #include "messages-ethereum.pb.h" +#define CHAIN_ID_UNKNOWN UINT64_MAX + void ethereum_signing_init(const EthereumSignTx *msg, const HDNode *node); void ethereum_signing_init_eip1559(const EthereumSignTxEIP1559 *msg, const HDNode *node); @@ -39,4 +41,6 @@ void ethereum_typed_hash_sign(const EthereumSignTypedHash *msg, EthereumTypedDataSignature *resp); bool ethereum_parse(const char *address, uint8_t pubkeyhash[20]); +bool ethereum_path_check(uint32_t address_n_count, const uint32_t *address_n, + bool pubkey_export, uint64_t chain); #endif diff --git a/legacy/firmware/ethereum_networks.h.mako b/legacy/firmware/ethereum_networks.h.mako index 6416aba39..5049f883c 100644 --- a/legacy/firmware/ethereum_networks.h.mako +++ b/legacy/firmware/ethereum_networks.h.mako @@ -3,14 +3,19 @@ BKSL = "\\" networks = list(supported_on("trezor1", eth)) max_chain_id_length = 0 +max_slip44_length = 0 max_suffix_length = 0 for n in networks: max_chain_id_length = max(len(str(n.chain_id)), max_chain_id_length) + max_slip44_length = max(len(str(n.slip44)), max_slip44_length) max_suffix_length = max(len(n.shortcut), max_suffix_length) def align_chain_id(n): return "{:>{w}}".format(n.chain_id, w=max_chain_id_length) +def align_slip44(n): + return "{:>{w}}".format(n.slip44, w=max_slip44_length) + def align_suffix(n): cstr = c_str(" " + n.shortcut) + ";" # we add two quotes, a space and a semicolon. hence +4 chars @@ -23,12 +28,34 @@ def align_suffix(n): #ifndef __ETHEREUM_NETWORKS_H__ #define __ETHEREUM_NETWORKS_H__ +#define SLIP44_UNKNOWN UINT32_MAX + #define ASSIGN_ETHEREUM_SUFFIX(suffix, chain_id) ${BKSL} - switch (chain_id) { ${BKSL} + switch (chain_id) { ${BKSL} +% for n in networks: + case ${align_chain_id(n)}: suffix = ${align_suffix(n)} break; /* ${n.name} */ ${BKSL} +% endfor + default: suffix = " UNKN"; break; /* unknown chain */ ${BKSL} + } + +static bool is_ethereum_slip44(uint32_t slip44) { + switch (slip44) { +% for slip44 in sorted(set(n.slip44 for n in networks)): + case ${slip44}: +% endfor + return true; + default: + return false; + } +} + +static int32_t ethereum_slip44_by_chain_id(uint64_t chain_id) { + switch (chain_id) { % for n in networks: - case ${align_chain_id(n)}: suffix = ${align_suffix(n)} break; /* ${n.name} */ ${BKSL} + case ${align_chain_id(n)}: return ${align_slip44(n)}; /* ${n.name} */ % endfor - default: suffix = " UNKN"; break; /* unknown chain */ ${BKSL} - } + default: return SLIP44_UNKNOWN; /* unknown chain */ + } +} #endif diff --git a/legacy/firmware/fsm_msg_ethereum.h b/legacy/firmware/fsm_msg_ethereum.h index 3ca3b1070..383433534 100644 --- a/legacy/firmware/fsm_msg_ethereum.h +++ b/legacy/firmware/fsm_msg_ethereum.h @@ -17,6 +17,22 @@ * along with this library. If not, see . */ +static bool fsm_ethereumCheckPath(uint32_t address_n_count, + const uint32_t *address_n, bool pubkey_export, + uint64_t chain_id) { + if (ethereum_path_check(address_n_count, address_n, pubkey_export, + chain_id)) { + return true; + } + + if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict) { + fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); + return false; + } + + return fsm_layoutPathWarning(); +} + void fsm_msgEthereumGetPublicKey(const EthereumGetPublicKey *msg) { RESP_INIT(EthereumPublicKey); @@ -28,6 +44,12 @@ void fsm_msgEthereumGetPublicKey(const EthereumGetPublicKey *msg) { const CoinInfo *coin = fsm_getCoin(true, "Bitcoin"); if (!coin) return; + if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, true, + CHAIN_ID_UNKNOWN)) { + layoutHome(); + return; + } + const char *curve = coin->curve_name; uint32_t fingerprint; HDNode *node = fsm_getDerivedNode(curve, msg->address_n, msg->address_n_count, @@ -71,6 +93,12 @@ void fsm_msgEthereumSignTx(const EthereumSignTx *msg) { CHECK_PIN + if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false, + msg->chain_id)) { + layoutHome(); + return; + } + const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; @@ -83,6 +111,12 @@ void fsm_msgEthereumSignTxEIP1559(const EthereumSignTxEIP1559 *msg) { CHECK_PIN + if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false, + msg->chain_id)) { + layoutHome(); + return; + } + const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; @@ -101,13 +135,22 @@ void fsm_msgEthereumGetAddress(const EthereumGetAddress *msg) { CHECK_PIN + if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false, + CHAIN_ID_UNKNOWN)) { + layoutHome(); + return; + } + const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; uint8_t pubkeyhash[20]; - if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) return; + if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) { + layoutHome(); + return; + } uint32_t slip44 = (msg->address_n_count > 1) ? (msg->address_n[1] & PATH_UNHARDEN_MASK) : 0; @@ -150,12 +193,19 @@ void fsm_msgEthereumSignMessage(const EthereumSignMessage *msg) { CHECK_PIN + if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false, + CHAIN_ID_UNKNOWN)) { + layoutHome(); + return; + } + const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; uint8_t pubkeyhash[20] = {0}; if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) { + layoutHome(); return; } @@ -230,6 +280,12 @@ void fsm_msgEthereumSignTypedHash(const EthereumSignTypedHash *msg) { return; } + if (!fsm_ethereumCheckPath(msg->address_n_count, msg->address_n, false, + CHAIN_ID_UNKNOWN)) { + layoutHome(); + return; + } + layoutDialogSwipe(&bmp_icon_warning, _("Abort"), _("Continue"), NULL, _("Unable to show"), _("EIP-712 data."), NULL, _("Sign at your own risk."), NULL, NULL); @@ -245,6 +301,7 @@ void fsm_msgEthereumSignTypedHash(const EthereumSignTypedHash *msg) { uint8_t pubkeyhash[20] = {0}; if (!hdnode_get_ethereum_pubkeyhash(node, pubkeyhash)) { + layoutHome(); return; } From 35151c61579c117fcabc44a2bd0e27c91b7f5ce7 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Wed, 26 Jan 2022 18:47:20 +0100 Subject: [PATCH 04/32] feat(legacy): Strict path validation for Stellar. --- legacy/firmware/fsm_msg_stellar.h | 25 +++++++++++++++++++++++++ legacy/firmware/stellar.c | 13 +++++++++++++ legacy/firmware/stellar.h | 2 ++ 3 files changed, 40 insertions(+) diff --git a/legacy/firmware/fsm_msg_stellar.h b/legacy/firmware/fsm_msg_stellar.h index 5eb4e41ac..44d920d87 100644 --- a/legacy/firmware/fsm_msg_stellar.h +++ b/legacy/firmware/fsm_msg_stellar.h @@ -17,6 +17,20 @@ * along with this library. If not, see . */ +static bool fsm_stellarCheckPath(uint32_t address_n_count, + const uint32_t *address_n) { + if (stellar_path_check(address_n_count, address_n)) { + return true; + } + + if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict) { + fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); + return false; + } + + return fsm_layoutPathWarning(); +} + void fsm_msgStellarGetAddress(const StellarGetAddress *msg) { RESP_INIT(StellarAddress); @@ -24,10 +38,16 @@ void fsm_msgStellarGetAddress(const StellarGetAddress *msg) { CHECK_PIN + if (!fsm_stellarCheckPath(msg->address_n_count, msg->address_n)) { + layoutHome(); + return; + } + const HDNode *node = stellar_deriveNode(msg->address_n, msg->address_n_count); if (!node) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to derive private key")); + layoutHome(); return; } @@ -55,6 +75,11 @@ void fsm_msgStellarSignTx(const StellarSignTx *msg) { CHECK_INITIALIZED CHECK_PIN + if (!fsm_stellarCheckPath(msg->address_n_count, msg->address_n)) { + layoutHome(); + return; + } + if (!stellar_signingInit(msg)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to derive private key")); diff --git a/legacy/firmware/stellar.c b/legacy/firmware/stellar.c index 886a68d62..55dde2337 100644 --- a/legacy/firmware/stellar.c +++ b/legacy/firmware/stellar.c @@ -2013,3 +2013,16 @@ void stellar_layoutTransactionDialog(const char *line1, const char *line2, line1, line2, line3, line4, line5, stellar_activeTx.address_n, stellar_activeTx.address_n_count, str_warning, false); } + +bool stellar_path_check(uint32_t address_n_count, const uint32_t *address_n) { + // SEP-0005 for non-UTXO-based currencies, defined by Stellar: + // https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md + // m/44'/coin_type'/account' + bool valid = (address_n_count == 3); + valid = valid && (address_n[0] == (PATH_HARDENED | 44)); + valid = valid && (address_n[1] == (PATH_HARDENED | 148) || + address_n[1] == (PATH_HARDENED | 1)); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + return valid; +} diff --git a/legacy/firmware/stellar.h b/legacy/firmware/stellar.h index 7ba4e8353..6e4163f87 100644 --- a/legacy/firmware/stellar.h +++ b/legacy/firmware/stellar.h @@ -117,4 +117,6 @@ bool stellar_validateAddress(const char *str_address); bool stellar_getAddressBytes(const char *str_address, uint8_t *out_bytes); uint16_t stellar_crc16(uint8_t *bytes, uint32_t length); +bool stellar_path_check(uint32_t address_n_count, const uint32_t *address_n); + #endif From 88efd7471007fd250328ae25f0abcfaeac71bd1a Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Wed, 26 Jan 2022 19:58:17 +0100 Subject: [PATCH 05/32] feat(legacy): Make Bitcoin path checks same as in core. --- .../firmware/.changelog.d/noissue.security.1 | 1 + legacy/firmware/crypto.c | 322 ++++++++---------- legacy/firmware/crypto.h | 8 +- legacy/firmware/fsm.h | 4 + legacy/firmware/fsm_msg_coin.h | 49 +-- legacy/firmware/signing.c | 11 +- .../bitcoin/test_signtx_invalid_path.py | 1 - 7 files changed, 186 insertions(+), 210 deletions(-) create mode 100644 legacy/firmware/.changelog.d/noissue.security.1 diff --git a/legacy/firmware/.changelog.d/noissue.security.1 b/legacy/firmware/.changelog.d/noissue.security.1 new file mode 100644 index 000000000..20b941c5e --- /dev/null +++ b/legacy/firmware/.changelog.d/noissue.security.1 @@ -0,0 +1 @@ +Make Bitcoin path checks as strict as in Trezor T. diff --git a/legacy/firmware/crypto.c b/legacy/firmware/crypto.c index ddcfc8444..1a1296d12 100644 --- a/legacy/firmware/crypto.c +++ b/legacy/firmware/crypto.c @@ -487,231 +487,204 @@ static bool check_cointype(const CoinInfo *coin, uint32_t slip44, bool full) { bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, uint32_t address_n_count, const uint32_t *address_n, - bool has_multisig, CoinPathCheckLevel level) { - // For level BASIC this function checks that a coin without strong replay - // protection doesn't access paths that are known to be used by another coin. - // Used by SignTx to ensure that a user cannot be coerced into signing a - // testnet transaction or a Litecoin transaction which in fact spends Bitcoin. - // For level KNOWN this function checks that the path is a recognized path for - // the given coin. Used by GetAddress to prevent ransom attacks where a user - // could be coerced to use an address with an unenumerable path. - // For level SCRIPT_TYPE this function makes the same checks as in level - // KNOWN, but includes script type checks. - - const bool check_known = (level >= CoinPathCheckLevel_KNOWN); - const bool check_script_type = (level >= CoinPathCheckLevel_SCRIPT_TYPE); + bool has_multisig, bool full_check) { + // This function checks that the path is a recognized path for the given coin. + // Used by GetAddress to prevent ransom attacks where a user could be coerced + // to use an address with an unenumerable path and used by SignTx to ensure + // that a user cannot be coerced into signing a testnet transaction or a + // Litecoin transaction which in fact spends Bitcoin. If full_check is true, + // then this function also checks that the path fully matches the script type + // and coin type. This is used to determine whether a warning should be shown. + + if (address_n_count == 0) { + return false; + } bool valid = true; // m/44' : BIP44 Legacy // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 44)) { - if (check_known) { - valid = valid && (address_n_count == 5); - } else { - valid = valid && (address_n_count >= 2); - } - valid = valid && check_cointype(coin, address_n[1], check_known); - if (check_script_type) { + if (address_n[0] == PATH_HARDENED + 44) { + valid = valid && (address_n_count == 5); + valid = valid && check_cointype(coin, address_n[1], full_check); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + valid = valid && (address_n[3] <= PATH_MAX_CHANGE); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { valid = valid && (script_type == InputScriptType_SPENDADDRESS); valid = valid && (!has_multisig); } - if (check_known) { - valid = valid && (address_n[2] & PATH_HARDENED); - valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); - valid = valid && (address_n[3] <= PATH_MAX_CHANGE); - valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); - } return valid; } - if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 45)) { - if (check_script_type) { - valid = valid && has_multisig; - } - + if (address_n[0] == PATH_HARDENED + 45) { if (address_n_count == 4) { // m/45' - BIP45 Copay Abandoned Multisig P2SH // m / purpose' / cosigner_index / change / address_index // Patterns without a coin_type field must be treated as Bitcoin paths. - valid = valid && check_cointype(coin, SLIP44_BITCOIN, check_known); - if (check_script_type) { - valid = valid && (script_type == InputScriptType_SPENDMULTISIG); - } - if (check_known) { - valid = valid && (address_n[1] <= 100); - valid = valid && (address_n[2] <= PATH_MAX_CHANGE); - valid = valid && (address_n[3] <= PATH_MAX_ADDRESS_INDEX); - } + valid = valid && check_cointype(coin, SLIP44_BITCOIN, false); + valid = valid && (address_n[1] <= 100); + valid = valid && (address_n[2] <= PATH_MAX_CHANGE); + valid = valid && (address_n[3] <= PATH_MAX_ADDRESS_INDEX); } else if (address_n_count == 5) { // Unchained Capital compatibility pattern. Will be removed in the // future. // m / 45' / coin_type' / account' / [0-1000000] / address_index - valid = valid && check_cointype(coin, address_n[1], check_known); - if (check_script_type) { - valid = valid && (script_type == InputScriptType_SPENDADDRESS || - script_type == InputScriptType_SPENDMULTISIG); - } - if (check_known) { - valid = valid && (address_n[2] & PATH_HARDENED); - valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); - valid = valid && (address_n[3] <= 1000000); - valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); - } + valid = valid && check_cointype(coin, address_n[1], full_check); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = + valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + valid = valid && (address_n[3] <= 1000000); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); } else if (address_n_count == 6) { // Unchained Capital compatibility pattern. Will be removed in the // future. // m/45'/coin_type'/account'/[0-1000000]/change/address_index // m/45'/coin_type/account/[0-1000000]/change/address_index valid = valid && - check_cointype(coin, PATH_HARDENED | address_n[1], check_known); - if (check_script_type) { - valid = valid && (script_type == InputScriptType_SPENDADDRESS || - script_type == InputScriptType_SPENDMULTISIG); - } - if (check_known) { - valid = valid && ((address_n[1] & PATH_HARDENED) == - (address_n[2] & PATH_HARDENED)); - valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); - valid = valid && (address_n[3] <= 1000000); - valid = valid && (address_n[4] <= PATH_MAX_CHANGE); - valid = valid && (address_n[5] <= PATH_MAX_ADDRESS_INDEX); - } + check_cointype(coin, PATH_HARDENED | address_n[1], full_check); + valid = valid && ((address_n[1] & PATH_HARDENED) == + (address_n[2] & PATH_HARDENED)); + valid = + valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + valid = valid && (address_n[3] <= 1000000); + valid = valid && (address_n[4] <= PATH_MAX_CHANGE); + valid = valid && (address_n[5] <= PATH_MAX_ADDRESS_INDEX); } else { - if (check_known) { - return false; - } + return false; + } + + if (full_check) { + valid = valid && (script_type == InputScriptType_SPENDADDRESS || + script_type == InputScriptType_SPENDMULTISIG); + valid = valid && has_multisig; } return valid; } - // m/48' - BIP48 Copay Multisig P2SH - // m / purpose' / coin_type' / account' / change / address_index - // Electrum: - // m / purpose' / coin_type' / account' / type' / change / address_index - if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 48)) { - if (check_known) { - valid = valid && (address_n_count == 5 || address_n_count == 6); - } else { - valid = valid && (address_n_count >= 2); - } - valid = valid && check_cointype(coin, address_n[1], check_known); - if (check_script_type) { - valid = valid && has_multisig; - // we do not support Multisig with Taproot yet - valid = valid && (script_type == InputScriptType_SPENDMULTISIG || - script_type == InputScriptType_SPENDP2SHWITNESS || - script_type == InputScriptType_SPENDWITNESS); - } - if (check_known) { - valid = valid && (address_n[2] & PATH_HARDENED); - valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); - if (address_n_count == 5) { - valid = valid && (address_n[3] <= PATH_MAX_CHANGE); - valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); - } else if (address_n_count == 6) { - valid = valid && (address_n[3] & PATH_HARDENED); - valid = valid && ((address_n[3] & 0x7fffffff) <= 3); - valid = valid && (address_n[4] <= PATH_MAX_CHANGE); - valid = valid && (address_n[5] <= PATH_MAX_ADDRESS_INDEX); - } else { - return false; + if (address_n[0] == PATH_HARDENED + 48) { + valid = valid && (address_n_count == 5 || address_n_count == 6); + valid = valid && check_cointype(coin, address_n[1], full_check); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + if (address_n_count == 5) { + // [OBSOLETE] m/48' Copay Multisig P2SH + // m / purpose' / coin_type' / account' / change / address_index + // NOTE: this pattern is not recognized by trezor-core + valid = valid && (address_n[3] <= PATH_MAX_CHANGE); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { + valid = valid && has_multisig; + valid = valid && (script_type == InputScriptType_SPENDMULTISIG); + } + } else if (address_n_count == 6) { + // BIP-48: + // m / purpose' / coin_type' / account' / type' / change / address_index + valid = valid && (address_n[3] & PATH_HARDENED); + uint32_t type = address_n[3] & PATH_UNHARDEN_MASK; + valid = valid && (type <= 2); + valid = valid && (type == 0 || coin->has_segwit); + valid = valid && (address_n[4] <= PATH_MAX_CHANGE); + valid = valid && (address_n[5] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { + valid = valid && has_multisig; + switch (type) { + case 0: + valid = valid && (script_type == InputScriptType_SPENDMULTISIG || + script_type == InputScriptType_SPENDADDRESS); + break; + case 1: + valid = valid && (script_type == InputScriptType_SPENDP2SHWITNESS); + break; + case 2: + valid = valid && (script_type == InputScriptType_SPENDWITNESS); + break; + default: + return false; + } } + } else { + return false; } return valid; } // m/49' : BIP49 SegWit // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 49)) { + if (address_n[0] == PATH_HARDENED + 49) { valid = valid && coin->has_segwit; - if (check_known) { - valid = valid && (address_n_count == 5); - } else { - valid = valid && (address_n_count >= 2); - } - valid = valid && check_cointype(coin, address_n[1], check_known); - if (check_script_type) { + valid = valid && (address_n_count == 5); + valid = valid && check_cointype(coin, address_n[1], full_check); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + valid = valid && (address_n[3] <= PATH_MAX_CHANGE); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { valid = valid && (script_type == InputScriptType_SPENDP2SHWITNESS); } - if (check_known) { - valid = valid && (address_n[2] & PATH_HARDENED); - valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); - valid = valid && (address_n[3] <= PATH_MAX_CHANGE); - valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); - } return valid; } // m/84' : BIP84 Native SegWit // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 84)) { + if (address_n[0] == PATH_HARDENED + 84) { valid = valid && coin->has_segwit; valid = valid && (coin->bech32_prefix != NULL); - if (check_known) { - valid = valid && (address_n_count == 5); - } else { - valid = valid && (address_n_count >= 2); - } - valid = valid && check_cointype(coin, address_n[1], check_known); - if (check_script_type) { + valid = valid && (address_n_count == 5); + valid = valid && check_cointype(coin, address_n[1], full_check); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + valid = valid && (address_n[3] <= PATH_MAX_CHANGE); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { valid = valid && (script_type == InputScriptType_SPENDWITNESS); } - if (check_known) { - valid = valid && (address_n[2] & PATH_HARDENED); - valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); - valid = valid && (address_n[3] <= PATH_MAX_CHANGE); - valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); - } return valid; } // m/86' : BIP86 Taproot // m / purpose' / coin_type' / account' / change / address_index - if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 86)) { + if (address_n[0] == PATH_HARDENED + 86) { valid = valid && coin->has_taproot; valid = valid && (coin->bech32_prefix != NULL); - if (check_known) { - valid = valid && (address_n_count == 5); - } else { - valid = valid && (address_n_count >= 2); - } - valid = valid && check_cointype(coin, address_n[1], check_known); - if (check_script_type) { + valid = valid && (address_n_count == 5); + valid = valid && check_cointype(coin, address_n[1], full_check); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + valid = valid && (address_n[3] <= PATH_MAX_CHANGE); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { // we do not support Multisig with Taproot yet valid = valid && !has_multisig; valid = valid && (script_type == InputScriptType_SPENDTAPROOT); } - if (check_known) { - valid = valid && (address_n[2] & PATH_HARDENED); - valid = valid && ((address_n[2] & 0x7fffffff) <= PATH_MAX_ACCOUNT); - valid = valid && (address_n[3] <= PATH_MAX_CHANGE); - valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); - } return valid; } // Green Address compatibility pattern. Will be removed in the future. // m / [1,4] / address_index - if (address_n_count > 0 && (address_n[0] == 1 || address_n[0] == 4)) { + if (address_n[0] == 1 || address_n[0] == 4) { valid = valid && (coin->coin_type == SLIP44_BITCOIN); - if (check_known) { - valid = valid && (address_n_count == 2); - valid = valid && (address_n[1] <= PATH_MAX_ADDRESS_INDEX); + valid = valid && (address_n_count == 2); + valid = valid && (address_n[1] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { + valid = valid && (script_type != InputScriptType_SPENDTAPROOT); } return valid; } // Green Address compatibility pattern. Will be removed in the future. // m / 3' / [1-100]' / [1,4] / address_index - if (address_n_count > 0 && address_n[0] == (PATH_HARDENED + 3)) { + if (address_n[0] == PATH_HARDENED + 3) { valid = valid && (coin->coin_type == SLIP44_BITCOIN); - if (check_known) { - valid = valid && (address_n_count == 4); - valid = valid && (address_n[1] & PATH_HARDENED); - valid = valid && ((address_n[1] & 0x7fffffff) <= 100); - valid = valid && (address_n[2] == 1 || address_n[2] == 4); - valid = valid && (address_n[3] <= PATH_MAX_ADDRESS_INDEX); + valid = valid && (address_n_count == 4); + valid = valid && (address_n[1] & PATH_HARDENED); + valid = valid && ((address_n[1] & PATH_UNHARDEN_MASK) <= 100); + valid = valid && (address_n[2] == 1 || address_n[2] == 4); + valid = valid && (address_n[3] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { + valid = valid && (script_type != InputScriptType_SPENDTAPROOT); } return valid; } @@ -719,41 +692,36 @@ bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, // Green Address compatibility patterns. Will be removed in the future. // m / 1195487518 // m / 1195487518 / 6 / address_index - if (address_n_count > 0 && address_n[0] == 1195487518) { + if (address_n[0] == 1195487518) { valid = valid && (coin->coin_type == SLIP44_BITCOIN); - if (check_known) { - if (address_n_count == 3) { - valid = valid && (address_n[1] == 6); - valid = valid && (address_n[2] <= PATH_MAX_ADDRESS_INDEX); - } else if (address_n_count != 1) { - return false; - } + if (address_n_count == 3) { + valid = valid && (address_n[1] == 6); + valid = valid && (address_n[2] <= PATH_MAX_ADDRESS_INDEX); + } else if (address_n_count != 1) { + return false; + } + if (full_check) { + return false; } return valid; } // Casa compatibility pattern. Will be removed in the future. // m / 49 / coin_type / account / change / address_index - if (address_n_count > 0 && address_n[0] == 49) { - if (check_known) { - valid = valid && (address_n_count == 5); - } else { - valid = valid && (address_n_count >= 2); - } - valid = valid && - check_cointype(coin, PATH_HARDENED | address_n[1], check_known); - if (check_script_type) { + if (address_n[0] == 49) { + valid = valid && (address_n_count == 5); + valid = + valid && check_cointype(coin, PATH_HARDENED | address_n[1], full_check); + valid = valid && ((address_n[1] & PATH_HARDENED) == 0); + valid = valid && (address_n[2] <= PATH_MAX_ACCOUNT); + valid = valid && (address_n[3] <= PATH_MAX_CHANGE); + valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); + if (full_check) { valid = valid && (script_type == InputScriptType_SPENDP2SHWITNESS); } - if (check_known) { - valid = valid && ((address_n[1] & PATH_HARDENED) == 0); - valid = valid && (address_n[2] <= PATH_MAX_ACCOUNT); - valid = valid && (address_n[3] <= PATH_MAX_CHANGE); - valid = valid && (address_n[4] <= PATH_MAX_ADDRESS_INDEX); - } return valid; } - // we allow unknown paths only when a full check is not required - return level == CoinPathCheckLevel_BASIC; + // unknown path + return false; } diff --git a/legacy/firmware/crypto.h b/legacy/firmware/crypto.h index b8675ccb6..04e98d374 100644 --- a/legacy/firmware/crypto.h +++ b/legacy/firmware/crypto.h @@ -32,12 +32,6 @@ #include "messages-bitcoin.pb.h" #include "messages-crypto.pb.h" -typedef enum _CoinPathCheckLevel { - CoinPathCheckLevel_BASIC = 0, - CoinPathCheckLevel_KNOWN = 1, - CoinPathCheckLevel_SCRIPT_TYPE = 2, -} CoinPathCheckLevel; - #define PATH_HARDENED 0x80000000 #define PATH_UNHARDEN_MASK 0x7fffffff #define PATH_MAX_ACCOUNT 100 @@ -85,6 +79,6 @@ int cryptoIdentityFingerprint(const IdentityType *identity, uint8_t *hash); bool coin_path_check(const CoinInfo *coin, InputScriptType script_type, uint32_t address_n_count, const uint32_t *address_n, - bool has_multisig, CoinPathCheckLevel level); + bool has_multisig, bool full_check); #endif diff --git a/legacy/firmware/fsm.h b/legacy/firmware/fsm.h index c22cca9bf..d005e1cfc 100644 --- a/legacy/firmware/fsm.h +++ b/legacy/firmware/fsm.h @@ -20,6 +20,7 @@ #ifndef __FSM_H__ #define __FSM_H__ +#include "coins.h" #include "messages-bitcoin.pb.h" #include "messages-crypto.pb.h" #include "messages-debug.pb.h" @@ -144,5 +145,8 @@ bool fsm_layoutSignMessage(const uint8_t *msg, uint32_t len); bool fsm_layoutVerifyMessage(const uint8_t *msg, uint32_t len); bool fsm_layoutPathWarning(void); +bool fsm_checkCoinPath(const CoinInfo *coin, InputScriptType script_type, + uint32_t address_n_count, const uint32_t *address_n, + bool has_multisig, bool show_warning); #endif diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index 71f4afcc3..36c5901a7 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -151,24 +151,25 @@ void fsm_msgTxAck(TxAck *msg) { signing_txack(&(msg->tx)); } -static bool fsm_checkCoinPath(const CoinInfo *coin, InputScriptType script_type, - uint32_t address_n_count, - const uint32_t *address_n, bool has_multisig) { - if (!coin_path_check(coin, script_type, address_n_count, address_n, - has_multisig, CoinPathCheckLevel_SCRIPT_TYPE)) { - if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict && - !coin_path_check(coin, script_type, address_n_count, address_n, - has_multisig, CoinPathCheckLevel_KNOWN)) { - fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); - layoutHome(); - return false; - } +bool fsm_checkCoinPath(const CoinInfo *coin, InputScriptType script_type, + uint32_t address_n_count, const uint32_t *address_n, + bool has_multisig, bool show_warning) { + if (coin_path_check(coin, script_type, address_n_count, address_n, + has_multisig, true)) { + return true; + } - if (!fsm_layoutPathWarning()) { - layoutHome(); - return false; - } + if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict && + !coin_path_check(coin, script_type, address_n_count, address_n, + has_multisig, false)) { + fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); + return false; } + + if (show_warning) { + return fsm_layoutPathWarning(); + } + return true; } @@ -181,6 +182,14 @@ void fsm_msgGetAddress(const GetAddress *msg) { const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name); if (!coin) return; + + if (!fsm_checkCoinPath(coin, msg->script_type, msg->address_n_count, + msg->address_n, msg->has_multisig, + msg->show_display)) { + layoutHome(); + return; + } + HDNode *node = fsm_getDerivedNode(coin->curve_name, msg->address_n, msg->address_n_count, NULL); if (!node) return; @@ -220,11 +229,6 @@ void fsm_msgGetAddress(const GetAddress *msg) { strlcpy(desc, _("Address:"), sizeof(desc)); } - if (!fsm_checkCoinPath(coin, msg->script_type, msg->address_n_count, - msg->address_n, msg->has_multisig)) { - return; - } - uint32_t multisig_xpub_magic = coin->xpub_magic; if (msg->has_multisig && coin->has_segwit) { if (!msg->has_ignore_xpub_magic || !msg->ignore_xpub_magic) { @@ -269,7 +273,8 @@ void fsm_msgSignMessage(const SignMessage *msg) { if (!coin) return; if (!fsm_checkCoinPath(coin, msg->script_type, msg->address_n_count, - msg->address_n, false)) { + msg->address_n, false, true)) { + layoutHome(); return; } diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index d26ba0ff7..1b00442b7 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -747,13 +747,12 @@ static bool fill_input_script_sig(TxInputType *tinput) { static bool derive_node(TxInputType *tinput) { if (!coin_path_check(coin, tinput->script_type, tinput->address_n_count, - tinput->address_n, tinput->has_multisig, - CoinPathCheckLevel_BASIC)) { + tinput->address_n, tinput->has_multisig, false)) { if (is_replacement) { fsm_sendFailure( FailureType_Failure_ProcessError, _("Non-standard paths not allowed in replacement transactions.")); - layoutHome(); + signing_abort(); return false; } @@ -1373,6 +1372,12 @@ static bool signing_add_input(TxInputType *txinput) { // hash all input data to check it later (relevant for fee computation) tx_input_check_hash(&hasher_check, txinput); + if (!fsm_checkCoinPath(coin, txinput->script_type, txinput->address_n_count, + txinput->address_n, txinput->has_multisig, true)) { + signing_abort(); + return false; + } + if (!fill_input_script_pubkey(coin, &root, txinput)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to derive scriptPubKey")); diff --git a/tests/device_tests/bitcoin/test_signtx_invalid_path.py b/tests/device_tests/bitcoin/test_signtx_invalid_path.py index cb8020133..69bf4efe4 100644 --- a/tests/device_tests/bitcoin/test_signtx_invalid_path.py +++ b/tests/device_tests/bitcoin/test_signtx_invalid_path.py @@ -174,7 +174,6 @@ def test_attack_path_segwit(client: Client): ) -@pytest.mark.skip_t1(reason="T1 only prevents using paths known to be altcoins") def test_invalid_path_fail_asap(client: Client): inp1 = messages.TxInputType( address_n=parse_path("m/0"), From abb5ab74e30616280dcb421ecbae0b84b1aeb73e Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Sat, 29 Jan 2022 16:18:12 +0100 Subject: [PATCH 06/32] feat(legacy): Strict path validation for NEM. --- legacy/firmware/fsm_msg_nem.h | 36 +++++++++++++++++++++++++++++- legacy/firmware/nem2.c | 42 +++++++++++++++++++++++++++++++++++ legacy/firmware/nem2.h | 3 +++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/legacy/firmware/fsm_msg_nem.h b/legacy/firmware/fsm_msg_nem.h index 40ebc6aae..c17b68a58 100644 --- a/legacy/firmware/fsm_msg_nem.h +++ b/legacy/firmware/fsm_msg_nem.h @@ -17,6 +17,21 @@ * along with this library. If not, see . */ +static bool fsm_nemCheckPath(uint32_t address_n_count, + const uint32_t *address_n, uint8_t network) { + if (nem_path_check(address_n_count, address_n, network, true)) { + return true; + } + + if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict && + !nem_path_check(address_n_count, address_n, network, false)) { + fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); + return false; + } + + return fsm_layoutPathWarning(); +} + void fsm_msgNEMGetAddress(NEMGetAddress *msg) { if (!msg->has_network) { msg->network = NEM_NETWORK_MAINNET; @@ -31,11 +46,19 @@ void fsm_msgNEMGetAddress(NEMGetAddress *msg) { RESP_INIT(NEMAddress); + if (!fsm_nemCheckPath(msg->address_n_count, msg->address_n, msg->network)) { + layoutHome(); + return; + } + HDNode *node = fsm_getDerivedNode(ED25519_KECCAK_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; - if (!hdnode_get_nem_address(node, msg->network, resp->address)) return; + if (!hdnode_get_nem_address(node, msg->network, resp->address)) { + layoutHome(); + return; + } if (msg->has_show_display && msg->show_display) { char desc[16]; @@ -116,6 +139,12 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) { RESP_INIT(NEMSignedTx); + if (!fsm_nemCheckPath(msg->transaction.address_n_count, + msg->transaction.address_n, msg->transaction.network)) { + layoutHome(); + return; + } + HDNode *node = fsm_getDerivedNode(ED25519_KECCAK_NAME, msg->transaction.address_n, msg->transaction.address_n_count, NULL); @@ -317,6 +346,11 @@ void fsm_msgNEMDecryptMessage(NEMDecryptMessage *msg) { CHECK_PIN + if (!fsm_nemCheckPath(msg->address_n_count, msg->address_n, msg->network)) { + layoutHome(); + return; + } + const HDNode *node = fsm_getDerivedNode(ED25519_KECCAK_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; diff --git a/legacy/firmware/nem2.c b/legacy/firmware/nem2.c index 6372e9007..f95ff2aef 100644 --- a/legacy/firmware/nem2.c +++ b/legacy/firmware/nem2.c @@ -20,6 +20,7 @@ #include "nem2.h" #include "aes/aes.h" +#include "crypto.h" #include "fsm.h" #include "gettext.h" #include "layout2.h" @@ -741,3 +742,44 @@ bool nem_mosaicFormatLevy(const NEMMosaicDefinition *definition, return false; } } + +bool nem_path_check(uint32_t address_n_count, const uint32_t *address_n, + uint8_t network, bool check_coin_type) { + bool valid = (address_n_count >= 3); + valid = valid && (address_n[0] == (PATH_HARDENED | 44)); + valid = valid && (address_n[1] == (PATH_HARDENED | 43) || + address_n[1] == (PATH_HARDENED | 1)); + valid = valid && (address_n[2] & PATH_HARDENED); + valid = valid && ((address_n[2] & PATH_UNHARDEN_MASK) <= PATH_MAX_ACCOUNT); + + if (address_n_count == 3) { + // SEP-0005 for non-UTXO-based currencies, defined by Stellar: + // https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md + // m/44'/coin_type'/account' + // No further checks required. + } else if (address_n_count == 5) { + // NanoWallet compatibility path + // "m/44'/coin_type'/account'/0'/0'" + valid = valid && (address_n[3] == (PATH_HARDENED | 0)); + valid = valid && (address_n[4] == (PATH_HARDENED | 0)); + } else { + return false; + } + + if (check_coin_type) { + // Check that the appropriate coin_type is set for the given network. + switch (network) { + case NEM_NETWORK_MAINNET: + case NEM_NETWORK_MIJIN: + valid = valid && (address_n[1] == (PATH_HARDENED | 43)); + break; + case NEM_NETWORK_TESTNET: + valid = valid && (address_n[1] == (PATH_HARDENED | 1)); + break; + default: + return false; + } + } + + return valid; +} diff --git a/legacy/firmware/nem2.h b/legacy/firmware/nem2.h index 05592756d..2f3e89c91 100644 --- a/legacy/firmware/nem2.h +++ b/legacy/firmware/nem2.h @@ -100,6 +100,9 @@ bool nem_mosaicFormatLevy(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier, uint8_t network, char *str_out, size_t size); +bool nem_path_check(uint32_t address_n_count, const uint32_t *address_n, + uint8_t network, bool check_coin_type); + static inline void nem_mosaicFormatName(const char *namespace, const char *mosaic, char *str_out, size_t size) { From b88e57a7c8a39e601b6d64f58ee44a4c66e27536 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Thu, 3 Feb 2022 13:16:26 +0100 Subject: [PATCH 07/32] tests: Fix device tests for path checks in GetAddress. --- .../reset_recovery/test_recovery_bip39_t1.py | 5 +++-- .../device_tests/reset_recovery/test_reset_bip39_t1.py | 5 +++-- tests/device_tests/test_bip32_speed.py | 10 +++++++++- tests/device_tests/test_debuglink.py | 3 ++- tests/device_tests/test_msg_change_wipe_code_t1.py | 3 ++- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/tests/device_tests/reset_recovery/test_recovery_bip39_t1.py b/tests/device_tests/reset_recovery/test_recovery_bip39_t1.py index 1798bba39..c5aa1da76 100644 --- a/tests/device_tests/reset_recovery/test_recovery_bip39_t1.py +++ b/tests/device_tests/reset_recovery/test_recovery_bip39_t1.py @@ -18,6 +18,7 @@ import pytest from trezorlib import device, messages from trezorlib.debuglink import TrezorClientDebugLink as Client +from trezorlib.tools import parse_path from ...common import MNEMONIC12 @@ -84,7 +85,7 @@ def test_pin_passphrase(client: Client): assert client.features.passphrase_protection is True # Do passphrase-protected action, PassphraseRequest should be raised - resp = client.call_raw(messages.GetAddress()) + resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0"))) assert isinstance(resp, messages.PassphraseRequest) client.call_raw(messages.Cancel()) @@ -135,7 +136,7 @@ def test_nopin_nopassphrase(client: Client): assert client.features.passphrase_protection is False # Do pin & passphrase-protected action, PassphraseRequest should NOT be raised - resp = client.call_raw(messages.GetAddress()) + resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0"))) assert isinstance(resp, messages.Address) diff --git a/tests/device_tests/reset_recovery/test_reset_bip39_t1.py b/tests/device_tests/reset_recovery/test_reset_bip39_t1.py index 95269f2ff..929c0f5da 100644 --- a/tests/device_tests/reset_recovery/test_reset_bip39_t1.py +++ b/tests/device_tests/reset_recovery/test_reset_bip39_t1.py @@ -19,6 +19,7 @@ from mnemonic import Mnemonic from trezorlib import device, messages from trezorlib.debuglink import TrezorClientDebugLink as Client +from trezorlib.tools import parse_path from ...common import generate_entropy @@ -87,7 +88,7 @@ def reset_device(client: Client, strength): assert resp.passphrase_protection is False # Do pin & passphrase-protected action, PassphraseRequest should NOT be raised - resp = client.call_raw(messages.GetAddress()) + resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0"))) assert isinstance(resp, messages.Address) @@ -186,7 +187,7 @@ def test_reset_device_256_pin(client: Client): assert resp.passphrase_protection is True # Do passphrase-protected action, PassphraseRequest should be raised - resp = client.call_raw(messages.GetAddress()) + resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0"))) assert isinstance(resp, messages.PassphraseRequest) client.call_raw(messages.Cancel()) diff --git a/tests/device_tests/test_bip32_speed.py b/tests/device_tests/test_bip32_speed.py index f6c9376f0..6043e0be6 100644 --- a/tests/device_tests/test_bip32_speed.py +++ b/tests/device_tests/test_bip32_speed.py @@ -18,8 +18,9 @@ import time import pytest -from trezorlib import btc +from trezorlib import btc, device from trezorlib.debuglink import TrezorClientDebugLink as Client +from trezorlib.messages import SafetyCheckLevel from trezorlib.tools import H_ pytestmark = [ @@ -29,6 +30,8 @@ pytestmark = [ def test_public_ckd(client: Client): + # disable safety checks to access non-standard paths + device.apply_settings(client, safety_checks=SafetyCheckLevel.PromptTemporarily) btc.get_address(client, "Bitcoin", []) # to compute root node via BIP39 for depth in range(8): @@ -41,6 +44,8 @@ def test_public_ckd(client: Client): def test_private_ckd(client: Client): + # disable safety checks to access non-standard paths + device.apply_settings(client, safety_checks=SafetyCheckLevel.PromptTemporarily) btc.get_address(client, "Bitcoin", []) # to compute root node via BIP39 for depth in range(8): @@ -54,6 +59,9 @@ def test_private_ckd(client: Client): def test_cache(client: Client): + # disable safety checks to access non-standard paths + device.apply_settings(client, safety_checks=SafetyCheckLevel.PromptTemporarily) + start = time.time() for x in range(10): btc.get_address(client, "Bitcoin", [x, 2, 3, 4, 5, 6, 7, 8]) diff --git a/tests/device_tests/test_debuglink.py b/tests/device_tests/test_debuglink.py index bb1824eb7..d8ee68d7a 100644 --- a/tests/device_tests/test_debuglink.py +++ b/tests/device_tests/test_debuglink.py @@ -18,6 +18,7 @@ import pytest from trezorlib import debuglink, device, messages, misc from trezorlib.debuglink import TrezorClientDebugLink as Client +from trezorlib.tools import parse_path from trezorlib.transport import udp from ..common import MNEMONIC12 @@ -40,7 +41,7 @@ def test_mnemonic(client: Client): @pytest.mark.skip_t2 @pytest.mark.setup_client(mnemonic=MNEMONIC12, pin="1234", passphrase="") def test_pin(client: Client): - resp = client.call_raw(messages.GetAddress()) + resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0"))) assert isinstance(resp, messages.PinMatrixRequest) state = client.debug.state() diff --git a/tests/device_tests/test_msg_change_wipe_code_t1.py b/tests/device_tests/test_msg_change_wipe_code_t1.py index 4d6b0a6c4..45e7ba167 100644 --- a/tests/device_tests/test_msg_change_wipe_code_t1.py +++ b/tests/device_tests/test_msg_change_wipe_code_t1.py @@ -19,6 +19,7 @@ import pytest from trezorlib import device, exceptions, messages from trezorlib.client import MAX_PIN_LENGTH from trezorlib.debuglink import TrezorClientDebugLink as Client +from trezorlib.tools import parse_path PinType = messages.PinMatrixRequestType @@ -177,7 +178,7 @@ def test_set_pin_to_wipe_code(client: Client): # Check that there is no PIN protection. client.init_device() assert client.features.pin_protection is False - resp = client.call_raw(messages.GetAddress()) + resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0"))) assert isinstance(resp, messages.Address) From 3553086e84e1e5d8c0473ff68f4a8dcd90265918 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Sat, 5 Feb 2022 10:50:55 +0100 Subject: [PATCH 08/32] feat(legacy): Strict path validation for CoSi. --- legacy/firmware/fsm_msg_crypto.h | 26 ++++++++++++++++++++++++++ legacy/firmware/layout2.c | 1 + 2 files changed, 27 insertions(+) diff --git a/legacy/firmware/fsm_msg_crypto.h b/legacy/firmware/fsm_msg_crypto.h index cae8e2bea..bb6fe22e7 100644 --- a/legacy/firmware/fsm_msg_crypto.h +++ b/legacy/firmware/fsm_msg_crypto.h @@ -235,6 +235,22 @@ void fsm_msgGetECDHSessionKey(const GetECDHSessionKey *msg) { layoutHome(); } +static bool fsm_checkCosiPath(uint32_t address_n_count, + const uint32_t *address_n) { + // The path should typically match "m / 10018' / [0-9]'", but we allow + // any path from the SLIP-18 domain "m / 10018' / *". + if (address_n_count >= 1 && address_n[0] == PATH_HARDENED + 10018) { + return true; + } + + if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict) { + fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); + return false; + } + + return fsm_layoutPathWarning(); +} + void fsm_msgCosiCommit(const CosiCommit *msg) { RESP_INIT(CosiCommitment); @@ -242,6 +258,11 @@ void fsm_msgCosiCommit(const CosiCommit *msg) { CHECK_PARAM(msg->has_data, _("No data provided")); + if (!fsm_checkCosiPath(msg->address_n_count, msg->address_n)) { + layoutHome(); + return; + } + layoutCosiCommitSign(msg->address_n, msg->address_n_count, msg->data.bytes, msg->data.size, false); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -285,6 +306,11 @@ void fsm_msgCosiSign(const CosiSign *msg) { CHECK_PARAM(msg->has_global_pubkey && msg->global_pubkey.size == 32, _("Invalid global pubkey")); + if (!fsm_checkCosiPath(msg->address_n_count, msg->address_n)) { + layoutHome(); + return; + } + layoutCosiCommitSign(msg->address_n, msg->address_n_count, msg->data.bytes, msg->data.size, true); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { diff --git a/legacy/firmware/layout2.c b/legacy/firmware/layout2.c index adbd22d4f..3c75f9784 100644 --- a/legacy/firmware/layout2.c +++ b/legacy/firmware/layout2.c @@ -1178,6 +1178,7 @@ void layoutNEMLevy(const NEMMosaicDefinition *definition, uint8_t network) { static inline bool is_slip18(const uint32_t *address_n, size_t address_n_count) { + // m / 10018' / [0-9]' return address_n_count == 2 && address_n[0] == (PATH_HARDENED + 10018) && (address_n[1] & PATH_HARDENED) && (address_n[1] & PATH_UNHARDEN_MASK) <= 9; From 458d6e1b4b99625fca4c883d7949bedc3c80d1ab Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Sat, 5 Feb 2022 10:51:10 +0100 Subject: [PATCH 09/32] fix(trezorctl): Fix BIP-32 path in CoSi help. [no changelog] --- python/src/trezorlib/cli/cosi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/trezorlib/cli/cosi.py b/python/src/trezorlib/cli/cosi.py index 8f9e9aeba..4607e7982 100644 --- a/python/src/trezorlib/cli/cosi.py +++ b/python/src/trezorlib/cli/cosi.py @@ -25,7 +25,7 @@ if TYPE_CHECKING: from ..client import TrezorClient from .. import messages -PATH_HELP = "BIP-32 path, e.g. m/44'/0'/0'/0/0" +PATH_HELP = "BIP-32 path, e.g. m/10018'/0'" @click.group(name="cosi") From 4c60f80f4438eadbb9d82bcd2d308d23e193e81c Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Thu, 17 Feb 2022 10:44:40 +0100 Subject: [PATCH 10/32] feat(legacy): Add state sanity check to fsm_msg*Ack() functions. --- legacy/firmware/fsm.c | 6 ++++++ legacy/firmware/fsm_msg_coin.h | 2 ++ legacy/firmware/fsm_msg_common.h | 6 +++++- legacy/firmware/fsm_msg_ethereum.h | 2 ++ legacy/firmware/fsm_msg_stellar.h | 26 ++++++++++++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/legacy/firmware/fsm.c b/legacy/firmware/fsm.c index c91908433..6ed250815 100644 --- a/legacy/firmware/fsm.c +++ b/legacy/firmware/fsm.c @@ -100,6 +100,12 @@ static uint8_t msg_resp[MSG_OUT_DECODED_SIZE] __attribute__((aligned)); return; \ } +#define CHECK_UNLOCKED \ + if (!session_isUnlocked()) { \ + layoutHome(); \ + return; \ + } + #define CHECK_PARAM(cond, errormsg) \ if (!(cond)) { \ fsm_sendFailure(FailureType_Failure_DataError, (errormsg)); \ diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index 36c5901a7..529b657b2 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -146,6 +146,8 @@ void fsm_msgSignTx(const SignTx *msg) { } void fsm_msgTxAck(TxAck *msg) { + CHECK_UNLOCKED + CHECK_PARAM(msg->has_tx, _("No transaction provided")); signing_txack(&(msg->tx)); diff --git a/legacy/firmware/fsm_msg_common.h b/legacy/firmware/fsm_msg_common.h index 594ae34db..8b396d1c8 100644 --- a/legacy/firmware/fsm_msg_common.h +++ b/legacy/firmware/fsm_msg_common.h @@ -516,7 +516,11 @@ void fsm_msgRecoveryDevice(const RecoveryDevice *msg) { msg->has_u2f_counter ? msg->u2f_counter : 0, dry_run); } -void fsm_msgWordAck(const WordAck *msg) { recovery_word(msg->word); } +void fsm_msgWordAck(const WordAck *msg) { + CHECK_UNLOCKED + + recovery_word(msg->word); +} void fsm_msgSetU2FCounter(const SetU2FCounter *msg) { layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, diff --git a/legacy/firmware/fsm_msg_ethereum.h b/legacy/firmware/fsm_msg_ethereum.h index 383433534..a03b66294 100644 --- a/legacy/firmware/fsm_msg_ethereum.h +++ b/legacy/firmware/fsm_msg_ethereum.h @@ -125,6 +125,8 @@ void fsm_msgEthereumSignTxEIP1559(const EthereumSignTxEIP1559 *msg) { } void fsm_msgEthereumTxAck(const EthereumTxAck *msg) { + CHECK_UNLOCKED + ethereum_signing_txack(msg); } diff --git a/legacy/firmware/fsm_msg_stellar.h b/legacy/firmware/fsm_msg_stellar.h index 44d920d87..b2ab413e6 100644 --- a/legacy/firmware/fsm_msg_stellar.h +++ b/legacy/firmware/fsm_msg_stellar.h @@ -97,6 +97,8 @@ void fsm_msgStellarSignTx(const StellarSignTx *msg) { } void fsm_msgStellarCreateAccountOp(const StellarCreateAccountOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmCreateAccountOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -115,6 +117,8 @@ void fsm_msgStellarCreateAccountOp(const StellarCreateAccountOp *msg) { } void fsm_msgStellarPaymentOp(const StellarPaymentOp *msg) { + CHECK_UNLOCKED + // This will display additional dialogs to the user if (!stellar_confirmPaymentOp(msg)) return; @@ -136,6 +140,8 @@ void fsm_msgStellarPaymentOp(const StellarPaymentOp *msg) { void fsm_msgStellarPathPaymentStrictReceiveOp( const StellarPathPaymentStrictReceiveOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmPathPaymentStrictReceiveOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -155,6 +161,8 @@ void fsm_msgStellarPathPaymentStrictReceiveOp( void fsm_msgStellarPathPaymentStrictSendOp( const StellarPathPaymentStrictSendOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmPathPaymentStrictSendOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -173,6 +181,8 @@ void fsm_msgStellarPathPaymentStrictSendOp( } void fsm_msgStellarManageBuyOfferOp(const StellarManageBuyOfferOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmManageBuyOfferOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -191,6 +201,8 @@ void fsm_msgStellarManageBuyOfferOp(const StellarManageBuyOfferOp *msg) { } void fsm_msgStellarManageSellOfferOp(const StellarManageSellOfferOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmManageSellOfferOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -210,6 +222,8 @@ void fsm_msgStellarManageSellOfferOp(const StellarManageSellOfferOp *msg) { void fsm_msgStellarCreatePassiveSellOfferOp( const StellarCreatePassiveSellOfferOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmCreatePassiveSellOfferOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -228,6 +242,8 @@ void fsm_msgStellarCreatePassiveSellOfferOp( } void fsm_msgStellarSetOptionsOp(const StellarSetOptionsOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmSetOptionsOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -246,6 +262,8 @@ void fsm_msgStellarSetOptionsOp(const StellarSetOptionsOp *msg) { } void fsm_msgStellarChangeTrustOp(const StellarChangeTrustOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmChangeTrustOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -264,6 +282,8 @@ void fsm_msgStellarChangeTrustOp(const StellarChangeTrustOp *msg) { } void fsm_msgStellarAllowTrustOp(const StellarAllowTrustOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmAllowTrustOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -282,6 +302,8 @@ void fsm_msgStellarAllowTrustOp(const StellarAllowTrustOp *msg) { } void fsm_msgStellarAccountMergeOp(const StellarAccountMergeOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmAccountMergeOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -300,6 +322,8 @@ void fsm_msgStellarAccountMergeOp(const StellarAccountMergeOp *msg) { } void fsm_msgStellarManageDataOp(const StellarManageDataOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmManageDataOp(msg)) return; if (stellar_allOperationsConfirmed()) { @@ -318,6 +342,8 @@ void fsm_msgStellarManageDataOp(const StellarManageDataOp *msg) { } void fsm_msgStellarBumpSequenceOp(const StellarBumpSequenceOp *msg) { + CHECK_UNLOCKED + if (!stellar_confirmBumpSequenceOp(msg)) return; if (stellar_allOperationsConfirmed()) { From e24e9fcdb39fc6686d1b2c8f31bac933a92a91d2 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Thu, 17 Feb 2022 11:02:06 +0100 Subject: [PATCH 11/32] fix(legacy): Check PIN before confirming critical dialogs. --- legacy/firmware/fsm_msg_common.h | 6 ++++++ legacy/firmware/fsm_msg_crypto.h | 16 ++++++++-------- legacy/firmware/fsm_msg_nem.h | 5 ++--- tests/device_tests/test_protection_levels.py | 16 +--------------- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/legacy/firmware/fsm_msg_common.h b/legacy/firmware/fsm_msg_common.h index 8b396d1c8..fb9dec4ab 100644 --- a/legacy/firmware/fsm_msg_common.h +++ b/legacy/firmware/fsm_msg_common.h @@ -251,6 +251,8 @@ void fsm_msgWipeDevice(const WipeDevice *msg) { } void fsm_msgGetEntropy(const GetEntropy *msg) { + CHECK_PIN + #if !DEBUG_RNG layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, _("Do you really want to"), _("send entropy?"), NULL, NULL, @@ -523,6 +525,8 @@ void fsm_msgWordAck(const WordAck *msg) { } void fsm_msgSetU2FCounter(const SetU2FCounter *msg) { + CHECK_PIN + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, _("Do you want to set"), _("the U2F counter?"), NULL, NULL, NULL, NULL); @@ -537,6 +541,8 @@ void fsm_msgSetU2FCounter(const SetU2FCounter *msg) { } void fsm_msgGetNextU2FCounter() { + CHECK_PIN + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, _("Do you want to"), _("increase and retrieve"), _("the U2F counter?"), NULL, NULL, NULL); diff --git a/legacy/firmware/fsm_msg_crypto.h b/legacy/firmware/fsm_msg_crypto.h index bb6fe22e7..7904be01a 100644 --- a/legacy/firmware/fsm_msg_crypto.h +++ b/legacy/firmware/fsm_msg_crypto.h @@ -75,6 +75,8 @@ void fsm_msgSignIdentity(const SignIdentity *msg) { CHECK_INITIALIZED + CHECK_PIN + layoutSignIdentity(&(msg->identity), msg->has_challenge_visual ? msg->challenge_visual : 0); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -83,8 +85,6 @@ void fsm_msgSignIdentity(const SignIdentity *msg) { return; } - CHECK_PIN - uint8_t hash[32]; if (cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { fsm_sendFailure(FailureType_Failure_DataError, _("Invalid identity")); @@ -179,6 +179,8 @@ void fsm_msgGetECDHSessionKey(const GetECDHSessionKey *msg) { CHECK_INITIALIZED + CHECK_PIN + layoutDecryptIdentity(&msg->identity); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); @@ -186,8 +188,6 @@ void fsm_msgGetECDHSessionKey(const GetECDHSessionKey *msg) { return; } - CHECK_PIN - uint8_t hash[32]; if (cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { fsm_sendFailure(FailureType_Failure_DataError, _("Invalid identity")); @@ -258,6 +258,8 @@ void fsm_msgCosiCommit(const CosiCommit *msg) { CHECK_PARAM(msg->has_data, _("No data provided")); + CHECK_PIN + if (!fsm_checkCosiPath(msg->address_n_count, msg->address_n)) { layoutHome(); return; @@ -271,8 +273,6 @@ void fsm_msgCosiCommit(const CosiCommit *msg) { return; } - CHECK_PIN - const HDNode *node = fsm_getDerivedNode(ED25519_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; @@ -311,6 +311,8 @@ void fsm_msgCosiSign(const CosiSign *msg) { return; } + CHECK_PIN + layoutCosiCommitSign(msg->address_n, msg->address_n_count, msg->data.bytes, msg->data.size, true); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -319,8 +321,6 @@ void fsm_msgCosiSign(const CosiSign *msg) { return; } - CHECK_PIN - const HDNode *node = fsm_getDerivedNode(ED25519_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; diff --git a/legacy/firmware/fsm_msg_nem.h b/legacy/firmware/fsm_msg_nem.h index c17b68a58..579ee50cb 100644 --- a/legacy/firmware/fsm_msg_nem.h +++ b/legacy/firmware/fsm_msg_nem.h @@ -333,6 +333,8 @@ void fsm_msgNEMDecryptMessage(NEMDecryptMessage *msg) { CHECK_PARAM(msg->has_public_key, _("No public key provided")); CHECK_PARAM(msg->public_key.size == 32, _("Invalid public key")); + CHECK_PIN + char address[NEM_ADDRESS_SIZE + 1]; nem_get_address(msg->public_key.bytes, msg->network, address); @@ -344,13 +346,10 @@ void fsm_msgNEMDecryptMessage(NEMDecryptMessage *msg) { return; } - CHECK_PIN - if (!fsm_nemCheckPath(msg->address_n_count, msg->address_n, msg->network)) { layoutHome(); return; } - const HDNode *node = fsm_getDerivedNode(ED25519_KECCAK_NAME, msg->address_n, msg->address_n_count, NULL); if (!node) return; diff --git a/tests/device_tests/test_protection_levels.py b/tests/device_tests/test_protection_levels.py index 9640859bf..e1ef5d2bf 100644 --- a/tests/device_tests/test_protection_levels.py +++ b/tests/device_tests/test_protection_levels.py @@ -158,21 +158,7 @@ def test_ping(client: Client): client.ping("msg", True) -@pytest.mark.skip_t2 -def test_get_entropy_t1(client: Client): - _assert_protection(client) - with client: - client.set_expected_responses( - [ - messages.ButtonRequest(code=B.ProtectCall), - messages.Entropy, - ] - ) - misc.get_entropy(client, 10) - - -@pytest.mark.skip_t1 -def test_get_entropy_t2(client: Client): +def test_get_entropy(client: Client): _assert_protection(client) with client: client.use_pin_sequence([PIN4]) From 84876dc9715e8927f9556daa642bce6ec38afa15 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Thu, 17 Feb 2022 17:16:42 +0100 Subject: [PATCH 12/32] feat(legacy): Add fsm_abortWorkflows(). --- .../firmware/.changelog.d/noissue.security.2 | 1 + legacy/firmware/config.c | 5 +- legacy/firmware/fsm.c | 9 ++ legacy/firmware/fsm.h | 2 + legacy/firmware/fsm_msg_common.h | 9 +- legacy/firmware/stellar.c | 136 +++++++++--------- legacy/firmware/stellar.h | 2 +- 7 files changed, 90 insertions(+), 74 deletions(-) create mode 100644 legacy/firmware/.changelog.d/noissue.security.2 diff --git a/legacy/firmware/.changelog.d/noissue.security.2 b/legacy/firmware/.changelog.d/noissue.security.2 new file mode 100644 index 000000000..893108612 --- /dev/null +++ b/legacy/firmware/.changelog.d/noissue.security.2 @@ -0,0 +1 @@ +Fix soft-lock bypass vulnerability. diff --git a/legacy/firmware/config.c b/legacy/firmware/config.c index 2eb0dfbb9..12a511070 100644 --- a/legacy/firmware/config.c +++ b/legacy/firmware/config.c @@ -431,7 +431,10 @@ void session_clearCache(Session *session) { session->seedCached = false; } -void config_lockDevice(void) { storage_lock(); } +void config_lockDevice(void) { + fsm_abortWorkflows(); + storage_lock(); +} static void get_u2froot_callback(uint32_t iter, uint32_t total) { layoutProgress(_("Updating"), 1000 * iter / total); diff --git a/legacy/firmware/fsm.c b/legacy/firmware/fsm.c index 6ed250815..122a4aada 100644 --- a/legacy/firmware/fsm.c +++ b/legacy/firmware/fsm.c @@ -376,6 +376,15 @@ void fsm_msgRebootToBootloader(void) { #endif } +void fsm_abortWorkflows(void) { + recovery_abort(); + signing_abort(); +#if !BITCOIN_ONLY + ethereum_signing_abort(); + stellar_signingAbort(); +#endif +} + bool fsm_layoutPathWarning(void) { layoutDialogSwipe(&bmp_icon_warning, _("Abort"), _("Continue"), NULL, _("Wrong address path"), _("for selected coin."), NULL, diff --git a/legacy/firmware/fsm.h b/legacy/firmware/fsm.h index d005e1cfc..5e9883e34 100644 --- a/legacy/firmware/fsm.h +++ b/legacy/firmware/fsm.h @@ -149,4 +149,6 @@ bool fsm_checkCoinPath(const CoinInfo *coin, InputScriptType script_type, uint32_t address_n_count, const uint32_t *address_n, bool has_multisig, bool show_warning); +void fsm_abortWorkflows(void); + #endif diff --git a/legacy/firmware/fsm_msg_common.h b/legacy/firmware/fsm_msg_common.h index fb9dec4ab..d031e91af 100644 --- a/legacy/firmware/fsm_msg_common.h +++ b/legacy/firmware/fsm_msg_common.h @@ -95,8 +95,7 @@ bool get_features(Features *resp) { } void fsm_msgInitialize(const Initialize *msg) { - recovery_abort(); - signing_abort(); + fsm_abortWorkflows(); uint8_t *session_id; if (msg && msg->has_session_id) { @@ -347,11 +346,7 @@ void fsm_msgBackupDevice(const BackupDevice *msg) { void fsm_msgCancel(const Cancel *msg) { (void)msg; - recovery_abort(); - signing_abort(); -#if !BITCOIN_ONLY - ethereum_signing_abort(); -#endif + fsm_abortWorkflows(); fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); } diff --git a/legacy/firmware/stellar.c b/legacy/firmware/stellar.c index 55dde2337..4d2ebaf92 100644 --- a/legacy/firmware/stellar.c +++ b/legacy/firmware/stellar.c @@ -155,6 +155,22 @@ bool stellar_signingInit(const StellarSignTx *msg) { return true; } +void stellar_signingAbort(void) { + if (stellar_signing) { + stellar_signing = false; + layoutHome(); + } +} + +static void stellar_signingFail(const char *reason) { + if (!reason) { + reason = _("Unknown error"); + } + fsm_sendFailure(FailureType_Failure_ProcessError, reason); + + stellar_signingAbort(); +} + bool stellar_confirmSourceAccount(bool has_source_account, const char *str_account) { stellar_hashupdate_bool(has_source_account); @@ -174,7 +190,7 @@ bool stellar_confirmSourceAccount(bool has_source_account, str_addr_rows[0], str_addr_rows[1], str_addr_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -189,7 +205,7 @@ bool stellar_confirmCreateAccountOp(const StellarCreateAccountOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -199,7 +215,7 @@ bool stellar_confirmCreateAccountOp(const StellarCreateAccountOp *msg) { // Validate new account and convert to bytes uint8_t new_account_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->new_account, new_account_bytes)) { - stellar_signingAbort(_("Invalid new account address")); + stellar_signingFail(_("Invalid new account address")); return false; } @@ -218,7 +234,7 @@ bool stellar_confirmCreateAccountOp(const StellarCreateAccountOp *msg) { str_addr_rows[1], str_addr_rows[2], str_amount_line); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -236,7 +252,7 @@ bool stellar_confirmPaymentOp(const StellarPaymentOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -247,7 +263,7 @@ bool stellar_confirmPaymentOp(const StellarPaymentOp *msg) { uint8_t destination_account_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->destination_account, destination_account_bytes)) { - stellar_signingAbort(_("Invalid destination account")); + stellar_signingFail(_("Invalid destination account")); return false; } @@ -273,7 +289,7 @@ bool stellar_confirmPaymentOp(const StellarPaymentOp *msg) { stellar_layoutTransactionDialog(str_pay_amount, str_asset_row, str_to, str_addr_rows[1], str_addr_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -295,7 +311,7 @@ bool stellar_confirmPathPaymentStrictReceiveOp( if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -306,7 +322,7 @@ bool stellar_confirmPathPaymentStrictReceiveOp( uint8_t destination_account_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->destination_account, destination_account_bytes)) { - stellar_signingAbort(_("Invalid destination account")); + stellar_signingFail(_("Invalid destination account")); return false; } const char **str_dest_rows = @@ -343,7 +359,7 @@ bool stellar_confirmPathPaymentStrictReceiveOp( stellar_layoutTransactionDialog(str_pay_amount, str_dest_asset, str_to, str_dest_rows[1], str_dest_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -360,7 +376,7 @@ bool stellar_confirmPathPaymentStrictReceiveOp( _("This is the max"), _("amount debited from your"), _("account.")); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } // Note: no confirmation for intermediate steps since they don't impact the @@ -394,7 +410,7 @@ bool stellar_confirmPathPaymentStrictSendOp( if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -405,7 +421,7 @@ bool stellar_confirmPathPaymentStrictSendOp( uint8_t destination_account_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->destination_account, destination_account_bytes)) { - stellar_signingAbort(_("Invalid destination account")); + stellar_signingFail(_("Invalid destination account")); return false; } const char **str_dest_rows = @@ -441,7 +457,7 @@ bool stellar_confirmPathPaymentStrictSendOp( stellar_layoutTransactionDialog(_("Path Pay at least"), str_pay_amount, str_dest_asset, str_to, str_dest_rows[1]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -458,7 +474,7 @@ bool stellar_confirmPathPaymentStrictSendOp( str_dest_rows[2], str_source_amount, str_send_asset, _("This is the amount debited"), _("from your account.")); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } // Note: no confirmation for intermediate steps since they don't impact the @@ -491,7 +507,7 @@ bool stellar_confirmManageBuyOfferOp(const StellarManageBuyOfferOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -551,7 +567,7 @@ bool stellar_confirmManageBuyOfferOp(const StellarManageBuyOfferOp *msg) { stellar_layoutTransactionDialog(str_offer, str_buying, str_buying_asset, str_selling, str_selling_asset); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -578,7 +594,7 @@ bool stellar_confirmManageSellOfferOp(const StellarManageSellOfferOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -637,7 +653,7 @@ bool stellar_confirmManageSellOfferOp(const StellarManageSellOfferOp *msg) { stellar_layoutTransactionDialog(str_offer, str_selling, str_selling_asset, str_buying, str_buying_asset); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -665,7 +681,7 @@ bool stellar_confirmCreatePassiveSellOfferOp( if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -715,7 +731,7 @@ bool stellar_confirmCreatePassiveSellOfferOp( stellar_layoutTransactionDialog(str_offer, str_selling, str_selling_asset, str_buying, str_buying_asset); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -740,7 +756,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -762,7 +778,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { uint8_t inflation_destination_account_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->inflation_destination_account, inflation_destination_account_bytes)) { - stellar_signingAbort(_("Invalid inflation destination account")); + stellar_signingFail(_("Invalid inflation destination account")); return false; } const char **str_addr_rows = @@ -771,7 +787,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { stellar_layoutTransactionDialog(str_title, NULL, str_addr_rows[0], str_addr_rows[1], str_addr_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -786,7 +802,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { // Auth required if (msg->clear_flags > 7) { - stellar_signingAbort(_("Invalid flags")); + stellar_signingFail(_("Invalid flags")); return false; } if (msg->clear_flags & 0x01) { @@ -807,7 +823,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { stellar_layoutTransactionDialog(str_title, rows[0], rows[1], rows[2], rows[3]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } memzero(rows, sizeof(rows)); @@ -824,7 +840,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { // Auth required if (msg->set_flags > 7) { - stellar_signingAbort(_("Invalid flags")); + stellar_signingFail(_("Invalid flags")); return false; } if (msg->set_flags & 0x01) { @@ -845,7 +861,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { stellar_layoutTransactionDialog(str_title, rows[0], rows[1], rows[2], rows[3]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } memzero(rows, sizeof(rows)); @@ -919,7 +935,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { stellar_layoutTransactionDialog(str_title, rows[0], rows[1], rows[2], rows[3]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } memzero(rows, sizeof(rows)); @@ -942,7 +958,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { stellar_layoutTransactionDialog(str_title, rows[0], rows[1], NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } memzero(rows, sizeof(rows)); @@ -982,7 +998,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { str_addr_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } break; @@ -998,12 +1014,12 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { _("screen)")); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } break; default: - stellar_signingAbort(_("Stellar: invalid signer type")); + stellar_signingFail(_("Stellar: invalid signer type")); return false; } @@ -1017,7 +1033,7 @@ bool stellar_confirmSetOptionsOp(const StellarSetOptionsOp *msg) { stellar_layoutTransactionDialog(_("Confirm Hash"), rows[0], rows[1], rows[2], rows[3]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } memzero(rows, sizeof(rows)); @@ -1042,7 +1058,7 @@ bool stellar_confirmChangeTrustOp(const StellarChangeTrustOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -1073,7 +1089,7 @@ bool stellar_confirmChangeTrustOp(const StellarChangeTrustOp *msg) { // Validate destination account and convert to bytes uint8_t asset_issuer_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->asset.issuer, asset_issuer_bytes)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); fsm_sendFailure(FailureType_Failure_ProcessError, _("Invalid asset issuer")); return false; @@ -1085,7 +1101,7 @@ bool stellar_confirmChangeTrustOp(const StellarChangeTrustOp *msg) { stellar_layoutTransactionDialog(str_title, str_amount_row, str_addr_rows[0], str_addr_rows[1], str_addr_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -1104,7 +1120,7 @@ bool stellar_confirmAllowTrustOp(const StellarAllowTrustOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -1126,7 +1142,7 @@ bool stellar_confirmAllowTrustOp(const StellarAllowTrustOp *msg) { // Validate account and convert to bytes uint8_t trusted_account_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->trusted_account, trusted_account_bytes)) { - stellar_signingAbort(_("Invalid trusted account")); + stellar_signingFail(_("Invalid trusted account")); return false; } @@ -1141,7 +1157,7 @@ bool stellar_confirmAllowTrustOp(const StellarAllowTrustOp *msg) { stellar_layoutTransactionDialog(str_title, str_asset_row, str_by, str_trustor_rows[1], str_trustor_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -1163,7 +1179,7 @@ bool stellar_confirmAllowTrustOp(const StellarAllowTrustOp *msg) { stellar_hashupdate_bytes((uint8_t *)padded_code, 12); break; default: - stellar_signingAbort(_("Stellar: invalid asset type")); + stellar_signingFail(_("Stellar: invalid asset type")); return false; } // is authorized @@ -1179,7 +1195,7 @@ bool stellar_confirmAccountMergeOp(const StellarAccountMergeOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -1190,7 +1206,7 @@ bool stellar_confirmAccountMergeOp(const StellarAccountMergeOp *msg) { uint8_t destination_account_bytes[STELLAR_KEY_SIZE] = {0}; if (!stellar_getAddressBytes(msg->destination_account, destination_account_bytes)) { - stellar_signingAbort(_("Invalid destination account")); + stellar_signingFail(_("Invalid destination account")); return false; } @@ -1202,7 +1218,7 @@ bool stellar_confirmAccountMergeOp(const StellarAccountMergeOp *msg) { str_destination_rows[0], str_destination_rows[1], str_destination_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -1219,7 +1235,7 @@ bool stellar_confirmManageDataOp(const StellarManageDataOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -1240,7 +1256,7 @@ bool stellar_confirmManageDataOp(const StellarManageDataOp *msg) { stellar_layoutTransactionDialog(str_title, str_key_lines[0], str_key_lines[1], str_key_lines[2], str_key_lines[3]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -1258,7 +1274,7 @@ bool stellar_confirmManageDataOp(const StellarManageDataOp *msg) { str_hash_lines[1], str_hash_lines[2], str_hash_lines[3]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } } @@ -1282,7 +1298,7 @@ bool stellar_confirmBumpSequenceOp(const StellarBumpSequenceOp *msg) { if (!stellar_confirmSourceAccount(msg->has_source_account, msg->source_account)) { - stellar_signingAbort(_("Source account error")); + stellar_signingFail(_("Source account error")); return false; } @@ -1295,7 +1311,7 @@ bool stellar_confirmBumpSequenceOp(const StellarBumpSequenceOp *msg) { stellar_layoutTransactionDialog(_("Bump Sequence"), _("Set sequence to:"), str_bump_to, NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return false; } @@ -1307,16 +1323,6 @@ bool stellar_confirmBumpSequenceOp(const StellarBumpSequenceOp *msg) { return true; } -void stellar_signingAbort(const char *reason) { - if (!reason) { - reason = _("Unknown error"); - } - - stellar_signing = false; - fsm_sendFailure(FailureType_Failure_ProcessError, reason); - layoutHome(); -} - /** * Populates the fields of resp with the signature of the active transaction */ @@ -1480,7 +1486,7 @@ void stellar_format_asset(const StellarAsset *asset, char *str_formatted, // Validate issuer account for non-native assets if (asset->type != StellarAssetType_NATIVE && !stellar_validateAddress(asset->issuer)) { - stellar_signingAbort(_("Invalid asset issuer")); + stellar_signingFail(_("Invalid asset issuer")); return; } @@ -1736,7 +1742,7 @@ void stellar_hashupdate_asset(const StellarAsset *asset) { uint8_t issuer_bytes[STELLAR_KEY_SIZE] = {0}; if (asset->type != StellarAssetType_NATIVE && !stellar_getAddressBytes(asset->issuer, issuer_bytes)) { - stellar_signingAbort(_("Invalid asset issuer")); + stellar_signingFail(_("Invalid asset issuer")); return; } @@ -1804,7 +1810,7 @@ void stellar_layoutTransactionSummary(const StellarSignTx *msg) { str_addr_rows[0], str_addr_rows[1], str_addr_rows[2]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return; } @@ -1839,7 +1845,7 @@ void stellar_layoutTransactionSummary(const StellarSignTx *msg) { strlcpy(str_lines[0], _("Memo (RETURN)"), sizeof(str_lines[0])); break; default: - stellar_signingAbort(_("Stellar invalid memo type")); + stellar_signingFail(_("Stellar invalid memo type")); return; } @@ -1853,7 +1859,7 @@ void stellar_layoutTransactionSummary(const StellarSignTx *msg) { stellar_layoutTransactionDialog(str_lines[0], str_lines[1], str_lines[2], str_lines[3], str_lines[4]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return; } @@ -1891,7 +1897,7 @@ void stellar_layoutTransactionSummary(const StellarSignTx *msg) { stellar_layoutTransactionDialog(_("Confirm Time Bounds"), str_lines[0], str_lines[1], str_lines[2], str_lines[3]); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - stellar_signingAbort(_("User canceled")); + stellar_signingFail(_("User canceled")); return; } } diff --git a/legacy/firmware/stellar.h b/legacy/firmware/stellar.h index 6e4163f87..f1aa5505e 100644 --- a/legacy/firmware/stellar.h +++ b/legacy/firmware/stellar.h @@ -54,7 +54,7 @@ typedef struct { // Signing process bool stellar_signingInit(const StellarSignTx *tx); -void stellar_signingAbort(const char *reason); +void stellar_signingAbort(void); bool stellar_confirmSourceAccount(bool has_source_account, const char *str_account); bool stellar_confirmCreateAccountOp(const StellarCreateAccountOp *msg); From f6f865a5139bdffd7c43d5610d9b2ffbc7ecb59b Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Thu, 17 Feb 2022 19:15:09 +0100 Subject: [PATCH 13/32] fix(tests): Update T1 UI test fixtures. --- tests/ui_tests/fixtures.json | 55 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 8fecf0cec..726dcdeb7 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -46,7 +46,7 @@ "T1_bitcoin-test_getaddress.py::test_ltc": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_getaddress.py::test_multisig": "09d812e81c04cef37608f181dcdefb6cd186eb5bb111d47ae0e62d1b3fdd64cf", "T1_bitcoin-test_getaddress.py::test_multisig_missing[False]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", -"T1_bitcoin-test_getaddress.py::test_multisig_missing[True]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", +"T1_bitcoin-test_getaddress.py::test_multisig_missing[True]": "ef912e3aed3113ed37f982568c0eca17c27feeb67e87e0f7e43cf8b3b3e8d199", "T1_bitcoin-test_getaddress.py::test_public_ckd": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_getaddress.py::test_tbtc": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_getaddress.py::test_tgrs": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", @@ -147,15 +147,15 @@ "T1_bitcoin-test_multisig_change.py::test_multisig_external_external": "988489b219d84517ca69893a8417a480309695549eb83f5821ebd52381e3a3a2", "T1_bitcoin-test_multisig_change.py::test_multisig_mismatch_change": "10dadffd94e286e588a7006906517205384084c493411191422bed806354caf8", "T1_bitcoin-test_multisig_change.py::test_multisig_mismatch_inputs": "dc50b96dc2f819f8bdccdb7b3d404580b0e08628e222f59661f91b13120c4ef5", -"T1_bitcoin-test_nonstandard_paths.py::test_getaddress[m-1195487518-6-255-script_types3]": "e6cfec9182dc6fc7e5b5ae63edf516a3a8db2bec008608e901c19c40c29b47a3", -"T1_bitcoin-test_nonstandard_paths.py::test_getaddress[m-1195487518-script_types2]": "e6d5e00fc42472a974be05181a0b071e0b78044bceb2fd02058303303e42edda", +"T1_bitcoin-test_nonstandard_paths.py::test_getaddress[m-1195487518-6-255-script_types3]": "c968d01488a358a7287c4e631996081bb490ff6e702b5ff84c3addba1c7b0974", +"T1_bitcoin-test_nonstandard_paths.py::test_getaddress[m-1195487518-script_types2]": "814c415655b03a6757056456544852a7ec88f8e96fbc97728eba7874d03782f8", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress[m-3h-100h-4-255-script_types1]": "f1d7f1ba4255576af0ffe4dd11dbc31dda17fec533495992a26bc1d22ade567a", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress[m-4-255-script_types0]": "df99b6bcfaf86d8ca67713ba64c085fb57b6fc6004494ef1cf83ccb4b57b8d4b", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress[m-49-0-63-0-255-script_types4]": "670669469e2de75d1164e7a0d5c8ad9c96520b0bf9d7aef85e5796853a375cdd", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths0-address_index0]": "3f11a25075140b6bb74d03d2eaf67559003cf5f46d07a778e2552bb281eaaaa8", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths1-address_index1]": "7c888498d7a49466b2ec128d523f5b7a4af29beccab3e4da8fdf3de2cc3e0e1e", -"T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths2-address_index2]": "44422270a72666e8fd508c86d3654a851aadc797fbb57a1d5c3a7bbc400911d2", -"T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths3-address_index3]": "e694e40bfe527e0488901d20dce70192f866c7aac61787c2220e79be439793f3", +"T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths2-address_index2]": "e8723bbbe5cb2484f3d1eda6fe19c48f23df6e96c36f6ff0d5d9d499ffc034a6", +"T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths3-address_index3]": "3ab904120014545ec65941dbaeb2c12c1659da2db495e62c5b3c4edd0dce3081", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths4-address_index4]": "c245c47efa462d2e6d487d81f131d3ae561c0f30ad90e55b53b48ba8b46ebea1", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths5-address_index5]": "81e4b1b39a135814413c96e9fa4e2639a8ab6b2cb9e945445ee12a99e994b523", "T1_bitcoin-test_nonstandard_paths.py::test_getaddress_multisig[paths6-address_index6]": "5d57a31f47490c5738af8136bf9ec8ee9d0db980d1653b9eaedace9d60e74119", @@ -164,20 +164,20 @@ "T1_bitcoin-test_nonstandard_paths.py::test_getpublicnode[m-3h-100h-4-255-script_types1]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_nonstandard_paths.py::test_getpublicnode[m-4-255-script_types0]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_nonstandard_paths.py::test_getpublicnode[m-49-0-63-0-255-script_types4]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", -"T1_bitcoin-test_nonstandard_paths.py::test_signmessage[m-1195487518-6-255-script_types3]": "ff92edfa61c3e98430d8fd7cd35f67ff237dc2b9d9d0a35256e11a8f81ffa317", -"T1_bitcoin-test_nonstandard_paths.py::test_signmessage[m-1195487518-script_types2]": "6e4c9ae9ab940e6b78862405d585cc1ebb42ecff42aff93af83d66e8b38f2a69", +"T1_bitcoin-test_nonstandard_paths.py::test_signmessage[m-1195487518-6-255-script_types3]": "4f7ee19b4e43a709ba945eb24d6bd2a9fe4785e33d54be937d8e3a2551b8d397", +"T1_bitcoin-test_nonstandard_paths.py::test_signmessage[m-1195487518-script_types2]": "510797e3346491fc7b3eb6f32f05e6b03640ed5cc8f3d70e1d85b77273578972", "T1_bitcoin-test_nonstandard_paths.py::test_signmessage[m-3h-100h-4-255-script_types1]": "bec27ce6240d3be57e2815b00f66db2f3d0da60b3de8429772aed5ce5dc0263a", "T1_bitcoin-test_nonstandard_paths.py::test_signmessage[m-4-255-script_types0]": "8501aeef2b2494e3440d4da64f2d08d24284183c1813753e653039797ffe684f", "T1_bitcoin-test_nonstandard_paths.py::test_signmessage[m-49-0-63-0-255-script_types4]": "3f99e0c68e5fb612cb48b7d170a5f36a32e1fc5d8fe7d98f391ef4900411731d", -"T1_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-6-255-script_types3]": "aa7cafa3fdf34ece7b4d7e1ad20c11d40e3582ed0473e1ea82b3fe6d02b151fa", -"T1_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-script_types2]": "aa7cafa3fdf34ece7b4d7e1ad20c11d40e3582ed0473e1ea82b3fe6d02b151fa", +"T1_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-6-255-script_types3]": "c8993b0932893430323d4fd34311ff6e13dc69c74247485ee1363fbc8c5b86c6", +"T1_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-script_types2]": "c8993b0932893430323d4fd34311ff6e13dc69c74247485ee1363fbc8c5b86c6", "T1_bitcoin-test_nonstandard_paths.py::test_signtx[m-3h-100h-4-255-script_types1]": "aa7cafa3fdf34ece7b4d7e1ad20c11d40e3582ed0473e1ea82b3fe6d02b151fa", "T1_bitcoin-test_nonstandard_paths.py::test_signtx[m-4-255-script_types0]": "aa7cafa3fdf34ece7b4d7e1ad20c11d40e3582ed0473e1ea82b3fe6d02b151fa", "T1_bitcoin-test_nonstandard_paths.py::test_signtx[m-49-0-63-0-255-script_types4]": "682610dc7fcea1c969063ed71b33ab36a62e165b331a713aa3b8148ddb5f6e95", "T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths0-address_index0]": "5c310bb0a73dc35ae1f2910b47ba319893b9039f1ed9762e67e9a97ebf1b6079", "T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths1-address_index1]": "5c310bb0a73dc35ae1f2910b47ba319893b9039f1ed9762e67e9a97ebf1b6079", -"T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths2-address_index2]": "5c310bb0a73dc35ae1f2910b47ba319893b9039f1ed9762e67e9a97ebf1b6079", -"T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths3-address_index3]": "5c310bb0a73dc35ae1f2910b47ba319893b9039f1ed9762e67e9a97ebf1b6079", +"T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths2-address_index2]": "95cf4ccb223cbe1171033da91fdc05802ceafed068fe7a56fedec000b8c421b4", +"T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths3-address_index3]": "95cf4ccb223cbe1171033da91fdc05802ceafed068fe7a56fedec000b8c421b4", "T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths4-address_index4]": "5c310bb0a73dc35ae1f2910b47ba319893b9039f1ed9762e67e9a97ebf1b6079", "T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths5-address_index5]": "5c310bb0a73dc35ae1f2910b47ba319893b9039f1ed9762e67e9a97ebf1b6079", "T1_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths6-address_index6]": "5c310bb0a73dc35ae1f2910b47ba319893b9039f1ed9762e67e9a97ebf1b6079", @@ -252,9 +252,10 @@ "T1_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "9640b4d0bdcde8fec8a4c077e1d12da211d02989458ad34115731237b3dad4f9", "T1_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "c478ef5c111b38c0fee1f79df1e0d00ecd5c0e81913e59051047cb0db65ece69", "T1_bitcoin-test_signtx_invalid_path.py::test_attack_path_segwit": "473636ae4c43d8a349db09187b74eb4c1aa2b7fe02742d5fa928cdbc2a9e4cfd", -"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail": "75e45c0b6039244afae5cb138aeb4eec2c01e71b91a3ce0d73797ca3b04ca94a", -"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_pass_forkid": "9c35bfcc194afff453802147f5b4a2d033492e564835be649c3293a62857de59", -"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_prompt": "57b20ea95e26ee7f675cbb177b9c781389ef36a02f2815f7939ab83c2d0f8f36", +"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", +"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail_asap": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", +"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_pass_forkid": "c83cf4f8324514dba0831e96fa2c20c30cef4121dcd594cf3232af19e4721a07", +"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_prompt": "0603601df63d976ca01ee3428d3f18f908695f500bb0c81e33483edd164b60f7", "T1_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_inputs": "5b980d57e7d1707d8802bff0665e0460fe5c594c91d758b05ee59020b72e3941", "T1_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_non_segwit_inputs": "704181fd5aa2ff33a9e5a27874187585ef946f7cdf6e690a7316a33921f25602", "T1_bitcoin-test_signtx_mixed_inputs.py::test_segwit_non_segwit_inputs": "5b980d57e7d1707d8802bff0665e0460fe5c594c91d758b05ee59020b72e3941", @@ -263,10 +264,10 @@ "T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash[hello world]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash[x]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", -"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[]": "9ec64a9408664533abd9b11973f15194a6e4df51abd77a549da8bf67a1f2577c", -"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[hello world]": "9ec64a9408664533abd9b11973f15194a6e4df51abd77a549da8bf67a1f2577c", -"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[x]": "9ec64a9408664533abd9b11973f15194a6e4df51abd77a549da8bf67a1f2577c", -"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "9ec64a9408664533abd9b11973f15194a6e4df51abd77a549da8bf67a1f2577c", +"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[]": "0aaaaec8e263055e9b26e93e839f8fa57c54f7dcebef9d7f94bc175712317c1d", +"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[hello world]": "0aaaaec8e263055e9b26e93e839f8fa57c54f7dcebef9d7f94bc175712317c1d", +"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[x]": "0aaaaec8e263055e9b26e93e839f8fa57c54f7dcebef9d7f94bc175712317c1d", +"T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "0aaaaec8e263055e9b26e93e839f8fa57c54f7dcebef9d7f94bc175712317c1d", "T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[]": "92816fb27c0fc626348c8ac485990305a824890ea5c862723d6cd53c7b558516", "T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[hello world]": "92816fb27c0fc626348c8ac485990305a824890ea5c862723d6cd53c7b558516", "T1_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[x]": "92816fb27c0fc626348c8ac485990305a824890ea5c862723d6cd53c7b558516", @@ -421,7 +422,7 @@ "T1_misc-test_msg_getentropy.py::test_entropy[8]": "10ee154b5db5599420a26df724cf2301afafb9bdb55429e4e091046881d589cb", "T1_misc-test_msg_getentropy.py::test_entropy[9]": "10ee154b5db5599420a26df724cf2301afafb9bdb55429e4e091046881d589cb", "T1_misc-test_msg_signidentity.py::test_sign": "237d6575385f61c32b574a23168330e40025eb9351202698f2d115db0e146934", -"T1_nem-test_getaddress.py::test_nem_getaddress": "e7ee9d6d0fdcf2009703fac7dcde878f72531587c20586d82cd9ca090647fb98", +"T1_nem-test_getaddress.py::test_nem_getaddress": "647dbd437bc7d5913ca7cbc8027d0230c3617e8b266f2c89e63c2d1342313557", "T1_nem-test_signtx_mosaics.py::test_nem_signtx_mosaic_creation": "74f2ed8d59e1aa1185ef7f06fe63e49380dfb185faa0e0d01656bc2bc8ff8c0c", "T1_nem-test_signtx_mosaics.py::test_nem_signtx_mosaic_creation_levy": "d782d6c77ea579238f6c5fc81adef34e0a47b4006ee4cf4556747ddc4afa998b", "T1_nem-test_signtx_mosaics.py::test_nem_signtx_mosaic_creation_properties": "014cdfbc54f7e6861fbc74e2c5729d6d5ce75b9774130d2cc62de413a96d05c9", @@ -432,9 +433,9 @@ "T1_nem-test_signtx_others.py::test_nem_signtx_importance_transfer": "7a63646daa836594fc56ba6f4d1af5deb0f1ea50c4e931a084ab1636a11546d8", "T1_nem-test_signtx_others.py::test_nem_signtx_provision_namespace": "11bb4a8dc8991471d8ed896691ebaecd0023b29432976ad519e92ece8f91a96a", "T1_nem-test_signtx_transfers.py::test_nem_signtx_encrypted_payload": "b1fd9c5250032b2decce6ef18cb1c6e06e9daea279039b58e01cc28a3f4dc765", -"T1_nem-test_signtx_transfers.py::test_nem_signtx_known_mosaic": "1efa8ae57b72b7a8220b4b9ad02dd0c08e3c9692673ebe7384144ad07fbc20c3", -"T1_nem-test_signtx_transfers.py::test_nem_signtx_known_mosaic_with_levy": "2b55781a0940df17fefdaf12ea46d5f794b15c7898f95a3ed82ccf86ec60871f", -"T1_nem-test_signtx_transfers.py::test_nem_signtx_multiple_mosaics": "cbd7f2a804a0d5c7014ee1bc484d23009ca78c1e220755ece35e99d444dd6f9d", +"T1_nem-test_signtx_transfers.py::test_nem_signtx_known_mosaic": "4de1af57a9f25b81ab5d29a6c96e2cd117145aae6cba3fedd083cac7f8cff1d7", +"T1_nem-test_signtx_transfers.py::test_nem_signtx_known_mosaic_with_levy": "ebc2635064a4469a98c2a4db2608ec3d006a69386d47e78bbbb8800bb0e7dc2a", +"T1_nem-test_signtx_transfers.py::test_nem_signtx_multiple_mosaics": "483194e161e010b5860086054fd1527ab79bbdfbf6fcbf556047a3e7f9d66d6d", "T1_nem-test_signtx_transfers.py::test_nem_signtx_simple": "3dac9a2abaab139be3b670d6f8e22d34db0171d09101b447c9de7011ad59b465", "T1_nem-test_signtx_transfers.py::test_nem_signtx_unknown_mosaic": "0fd4bec396dc0850d42a43fb6bd23a751565ef143870ae21e1c1ff5faaeb1bef", "T1_nem-test_signtx_transfers.py::test_nem_signtx_xem_as_mosaic": "9cc4d7978b6296e0d107a20912e4dedcc9ed6eb3229749a7fb515827c85f18ee", @@ -517,9 +518,9 @@ "T1_test_basic.py::test_device_id_same": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_test_basic.py::test_features": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_test_basic.py::test_ping": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", -"T1_test_bip32_speed.py::test_cache": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", -"T1_test_bip32_speed.py::test_private_ckd": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", -"T1_test_bip32_speed.py::test_public_ckd": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", +"T1_test_bip32_speed.py::test_cache": "55f043b3e286b778a02baea8f7c3547208849e2e18f90837bd9374a4a14c5c0b", +"T1_test_bip32_speed.py::test_private_ckd": "55f043b3e286b778a02baea8f7c3547208849e2e18f90837bd9374a4a14c5c0b", +"T1_test_bip32_speed.py::test_public_ckd": "55f043b3e286b778a02baea8f7c3547208849e2e18f90837bd9374a4a14c5c0b", "T1_test_cancel.py::test_cancel_message_via_cancel[message0]": "de7fc40b2f35e82fa486f1b97ee3e34a96d0a67412537e8a0fddacc0b0b1649d", "T1_test_cancel.py::test_cancel_message_via_cancel[message1]": "af93b5d0a8ae6b297391a43ff3f6382d0bea1109f4f411f5b306e2e7ced6e814", "T1_test_cancel.py::test_cancel_message_via_initialize[message0]": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", @@ -568,7 +569,7 @@ "T1_test_protection_levels.py::test_apply_settings": "af9edc0f8ab95a119d48f8ba3dad120dd95459eb8ec01a7cc8e3e5d8cd615981", "T1_test_protection_levels.py::test_change_pin_t1": "b03b10c08880556b5b5b3909f9d55486b4b27079eb0b56ce339ca020521ab664", "T1_test_protection_levels.py::test_get_address": "5b7419ecda88e49d9a55af9e7c7dc6d96e5992e11515299c7794de6e2e834eef", -"T1_test_protection_levels.py::test_get_entropy_t1": "8af3b06ff6827712110f4fb4a5ae6dced3d96022065aba9cbcfc50ca769fef19", +"T1_test_protection_levels.py::test_get_entropy": "a858148a335093e46872966e6411cd1bf9d0899bba6a3c798d7535e01461273b", "T1_test_protection_levels.py::test_get_public_key": "5b7419ecda88e49d9a55af9e7c7dc6d96e5992e11515299c7794de6e2e834eef", "T1_test_protection_levels.py::test_initialize": "3f4bd58ada8b2be88ceaf45b3653e940bd52f48eb42bd5ee43c0a8c7dd392139", "T1_test_protection_levels.py::test_passphrase_cached": "79a607736c6833a04561231c8db1df8cf6ac186715fc3798be9cc3456a588e24", @@ -1560,7 +1561,7 @@ "TT_test_protection_levels.py::test_apply_settings": "2451a804df4a867fef29adf4b71445352a3bface95a797f65bb87cf58c1ef34f", "TT_test_protection_levels.py::test_change_pin_t2": "d414bdebe6ea6b0f754aec1cdde61133b87fd27cf791ab1bdfdb61866a400d6c", "TT_test_protection_levels.py::test_get_address": "f0ac110de788b3112e04dc2ef131fca011a8dea1c309df37adeb23066729e273", -"TT_test_protection_levels.py::test_get_entropy_t2": "539ac09590d3252f0ccb2eb836c703a16be5a219c8bd46add57be8319a336ae9", +"TT_test_protection_levels.py::test_get_entropy": "539ac09590d3252f0ccb2eb836c703a16be5a219c8bd46add57be8319a336ae9", "TT_test_protection_levels.py::test_get_public_key": "f0ac110de788b3112e04dc2ef131fca011a8dea1c309df37adeb23066729e273", "TT_test_protection_levels.py::test_initialize": "59e518cba8589979f0af46e2acb211d37c96312f1d1a63a899d138ebb2f3ca29", "TT_test_protection_levels.py::test_passphrase_cached": "7fe34cc300a6f3547eaf72ab4339b758469f1e2722244d2a14d06e55ab1a3716", From 09d143079b19398c9c20985803115a7f0889c362 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 11 Feb 2022 11:30:31 +0100 Subject: [PATCH 14/32] chore(legacy/firmware): Bump FIX_VERSION to 1.11.0. --- legacy/firmware/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy/firmware/version.h b/legacy/firmware/version.h index f6ee0be70..19397afe9 100644 --- a/legacy/firmware/version.h +++ b/legacy/firmware/version.h @@ -3,5 +3,5 @@ #define VERSION_PATCH 1 #define FIX_VERSION_MAJOR 1 -#define FIX_VERSION_MINOR 10 +#define FIX_VERSION_MINOR 11 #define FIX_VERSION_PATCH 0 From 181fd1c6013d9ffdb11f11cd1aabaaa897845148 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 11 Mar 2022 12:25:53 +0100 Subject: [PATCH 15/32] fix(legacy): Stricter Bitcoin transaction checks. [no changelog] --- legacy/firmware/signing.c | 30 +++++++++++++++++++++++++----- legacy/firmware/transaction.c | 29 ++++++++++++++++++++++------- legacy/firmware/transaction.h | 2 +- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index 1b00442b7..4db1918c7 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -1370,7 +1370,12 @@ static void tx_info_finish(TxInfo *tx_info) { static bool signing_add_input(TxInputType *txinput) { // hash all input data to check it later (relevant for fee computation) - tx_input_check_hash(&hasher_check, txinput); + if (!tx_input_check_hash(&hasher_check, txinput)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to hash input")); + signing_abort(); + return false; + } if (!fsm_checkCoinPath(coin, txinput->script_type, txinput->address_n_count, txinput->address_n, txinput->has_multisig, true)) { @@ -1634,8 +1639,13 @@ static bool signing_add_orig_input(TxInputType *orig_input) { return false; } - // The first original input that has address_n set and a signature gets chosen - // as the verification input. Set script_sig for legacy digest computation. + // The first original non-multisig input that has address_n set and a + // signature gets chosen as the verification input. Set script_sig for legacy + // digest computation. + // NOTE: Supporting replacement transactions where all internal inputs are + // multisig would require checking the signatures of all of the original + // internal inputs or not allowing unverified external inputs in transactions + // where multisig inputs are present. if (!have_orig_verif_input && orig_input->address_n_count != 0 && !orig_input->has_multisig && ((orig_input->has_script_sig && orig_input->script_sig.size != 0) || @@ -2736,7 +2746,12 @@ void signing_txack(TransactionType *tx) { if (idx1 == 0) { hasher_Reset(&hasher_check); } - tx_input_check_hash(&hasher_check, tx->inputs); + if (!tx_input_check_hash(&hasher_check, tx->inputs)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to hash input")); + signing_abort(); + return; + } memcpy(&input, tx->inputs, sizeof(TxInputType)); @@ -2943,7 +2958,12 @@ void signing_txack(TransactionType *tx) { hasher_Reset(&hasher_check); } // check inputs are the same as those in phase 1 - tx_input_check_hash(&hasher_check, tx->inputs); + if (!tx_input_check_hash(&hasher_check, tx->inputs)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to hash input")); + signing_abort(); + return; + } if (idx2 == idx1) { if (!tx_info_check_input(&info, &tx->inputs[0]) || !derive_node(&tx->inputs[0]) || diff --git a/legacy/firmware/transaction.c b/legacy/firmware/transaction.c index 49a9a9aea..f60a43c60 100644 --- a/legacy/firmware/transaction.c +++ b/legacy/firmware/transaction.c @@ -556,22 +556,37 @@ uint32_t serialize_script_multisig(const CoinInfo *coin, } // tx methods -void tx_input_check_hash(Hasher *hasher, const TxInputType *input) { - hasher_Update(hasher, input->prev_hash.bytes, sizeof(input->prev_hash.bytes)); - hasher_Update(hasher, (const uint8_t *)&input->prev_index, - sizeof(input->prev_index)); - hasher_Update(hasher, (const uint8_t *)&input->script_type, - sizeof(input->script_type)); +bool tx_input_check_hash(Hasher *hasher, const TxInputType *input) { hasher_Update(hasher, (const uint8_t *)&input->address_n_count, sizeof(input->address_n_count)); for (int i = 0; i < input->address_n_count; ++i) hasher_Update(hasher, (const uint8_t *)&input->address_n[i], sizeof(input->address_n[0])); + hasher_Update(hasher, input->prev_hash.bytes, sizeof(input->prev_hash.bytes)); + hasher_Update(hasher, (const uint8_t *)&input->prev_index, + sizeof(input->prev_index)); + tx_script_hash(hasher, input->script_sig.size, input->script_sig.bytes); hasher_Update(hasher, (const uint8_t *)&input->sequence, sizeof(input->sequence)); + hasher_Update(hasher, (const uint8_t *)&input->script_type, + sizeof(input->script_type)); + uint8_t multisig_fp[32] = {0}; + if (input->has_multisig) { + if (cryptoMultisigFingerprint(&input->multisig, multisig_fp) == 0) { + // Invalid multisig parameters. + return false; + } + } + hasher_Update(hasher, multisig_fp, sizeof(multisig_fp)); hasher_Update(hasher, (const uint8_t *)&input->amount, sizeof(input->amount)); + tx_script_hash(hasher, input->witness.size, input->witness.bytes); + hasher_Update(hasher, (const uint8_t *)&input->has_orig_hash, + sizeof(input->has_orig_hash)); + hasher_Update(hasher, input->orig_hash.bytes, sizeof(input->orig_hash.bytes)); + hasher_Update(hasher, (const uint8_t *)&input->orig_index, + sizeof(input->orig_index)); tx_script_hash(hasher, input->script_pubkey.size, input->script_pubkey.bytes); - return; + return true; } uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input) { diff --git a/legacy/firmware/transaction.h b/legacy/firmware/transaction.h index 5d6094e0b..3929a72b3 100644 --- a/legacy/firmware/transaction.h +++ b/legacy/firmware/transaction.h @@ -79,7 +79,7 @@ int compile_output(const CoinInfo *coin, AmountUnit amount_unit, int fill_input_script_pubkey(const CoinInfo *coin, const HDNode *root, TxInputType *in); -void tx_input_check_hash(Hasher *hasher, const TxInputType *input); +bool tx_input_check_hash(Hasher *hasher, const TxInputType *input); uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input); uint32_t tx_amount_hash(Hasher *hasher, const TxInputType *input); uint32_t tx_script_hash(Hasher *hasher, uint32_t size, const uint8_t *data); From b1c6b4220153c2edb2cac9e3d15fabd6802a69e3 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 11 Mar 2022 12:26:05 +0100 Subject: [PATCH 16/32] fix(core): Stricter Bitcoin transaction checks. --- core/.changelog.d/noissue.security | 1 + core/src/apps/bitcoin/sign_tx/tx_info.py | 7 +++++-- core/src/apps/bitcoin/writers.py | 18 ++++++++++++------ .../tests/test_apps.bitcoin.sign_tx.writers.py | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 core/.changelog.d/noissue.security diff --git a/core/.changelog.d/noissue.security b/core/.changelog.d/noissue.security new file mode 100644 index 000000000..552e050cd --- /dev/null +++ b/core/.changelog.d/noissue.security @@ -0,0 +1 @@ +Fix a coin loss vulnerability related to replacement transactions with multisig inputs and unverified external inputs. diff --git a/core/src/apps/bitcoin/sign_tx/tx_info.py b/core/src/apps/bitcoin/sign_tx/tx_info.py index 5272ae50c..8944f3a66 100644 --- a/core/src/apps/bitcoin/sign_tx/tx_info.py +++ b/core/src/apps/bitcoin/sign_tx/tx_info.py @@ -153,8 +153,11 @@ class OriginalTxInfo(TxInfoBase): super().add_input(txi, script_pubkey) writers.write_tx_input(self.h_tx, txi, txi.script_sig or bytes()) - # For verification use the first original input that specifies address_n. - if not self.verification_input and txi.address_n: + # For verification use the first original non-multisig input that specifies address_n. + # NOTE: Supporting replacement transactions where all internal inputs are multisig would + # require checking the signatures of all of the original internal inputs or not allowing + # unverified external inputs in transactions where multisig inputs are present. + if not self.verification_input and txi.address_n and not txi.multisig: self.verification_input = txi self.verification_index = self.index diff --git a/core/src/apps/bitcoin/writers.py b/core/src/apps/bitcoin/writers.py index 7bedde242..e0680ae24 100644 --- a/core/src/apps/bitcoin/writers.py +++ b/core/src/apps/bitcoin/writers.py @@ -15,8 +15,6 @@ from apps.common.writers import ( # noqa: F401 write_uint64_le, ) -from .common import input_is_external_unverified - if TYPE_CHECKING: from trezor.messages import ( PrevInput, @@ -48,15 +46,23 @@ def write_tx_input(w: Writer, i: TxInput | PrevInput, script: bytes) -> None: def write_tx_input_check(w: Writer, i: TxInput) -> None: - write_bytes_fixed(w, i.prev_hash, TX_HASH_SIZE) - write_uint32(w, i.prev_index) - write_uint32(w, i.script_type) - write_uint8(w, input_is_external_unverified(i)) + from .multisig import multisig_fingerprint + write_uint32(w, len(i.address_n)) for n in i.address_n: write_uint32(w, n) + write_bytes_fixed(w, i.prev_hash, TX_HASH_SIZE) + write_uint32(w, i.prev_index) + write_bytes_prefixed(w, i.script_sig or b"") write_uint32(w, i.sequence) + write_uint32(w, i.script_type) + multisig_fp = multisig_fingerprint(i.multisig) if i.multisig else b"" + write_bytes_prefixed(w, multisig_fp) write_uint64(w, i.amount or 0) + write_bytes_prefixed(w, i.witness or b"") + write_bytes_prefixed(w, i.ownership_proof or b"") + write_bytes_prefixed(w, i.orig_hash or b"") + write_uint32(w, i.orig_index or 0) write_bytes_prefixed(w, i.script_pubkey or b"") diff --git a/core/tests/test_apps.bitcoin.sign_tx.writers.py b/core/tests/test_apps.bitcoin.sign_tx.writers.py index 65491cccb..0dd6949b8 100644 --- a/core/tests/test_apps.bitcoin.sign_tx.writers.py +++ b/core/tests/test_apps.bitcoin.sign_tx.writers.py @@ -43,7 +43,7 @@ class TestWriters(unittest.TestCase): b = bytearray() writers.write_tx_input_check(b, inp) - self.assertEqual(len(b), 32 + 4 + 4 + 1 + 4 + 4 + 4 + 8 + 26) + self.assertEqual(len(b), 4 + 4 + 32 + 4 + 11 + 4 + 4 + 1 + 8 + 1 + 1 + 1 + 4 + 26) for bad_prevhash in (b"", b"x", b"hello", b"x" * 33): inp.prev_hash = bad_prevhash From df479adbe79fa6779d7ddabf3b378497ea6412f8 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Tue, 15 Mar 2022 13:39:36 +0100 Subject: [PATCH 17/32] chore(legacy): Simplify path warning UI. [no changelog] --- legacy/firmware/signing.c | 57 ++++++++++++++++++++++-------------- tests/ui_tests/fixtures.json | 4 +-- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index 4db1918c7..7fb241726 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -66,6 +66,7 @@ enum { STAGE_REQUEST_DECRED_WITNESS, #endif } signing_stage; +static bool foreign_address_confirmed; // indicates that user approved warning static bool taproot_only; // indicates whether all internal inputs are Taproot static uint32_t idx1; // The index of the input or output in the current tx // which is being processed, signed or serialized. @@ -747,25 +748,24 @@ static bool fill_input_script_sig(TxInputType *tinput) { static bool derive_node(TxInputType *tinput) { if (!coin_path_check(coin, tinput->script_type, tinput->address_n_count, - tinput->address_n, tinput->has_multisig, false)) { - if (is_replacement) { - fsm_sendFailure( - FailureType_Failure_ProcessError, - _("Non-standard paths not allowed in replacement transactions.")); - signing_abort(); - return false; - } - - if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict) { - fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); - signing_abort(); - return false; - } + tinput->address_n, tinput->has_multisig, false) && + config_getSafetyCheckLevel() == SafetyCheckLevel_Strict) { + fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); + signing_abort(); + return false; + } - if (!fsm_layoutPathWarning()) { - signing_abort(); - return false; - } + // Sanity check not critical for security. The main reason for this is that we + // are not comfortable with using the same private key in multiple signature + // schemes (ECDSA and Schnorr) and we want to be sure that the user went + // through a warning screen before we sign the input. + if (!foreign_address_confirmed && + !coin_path_check(coin, tinput->script_type, tinput->address_n_count, + tinput->address_n, tinput->has_multisig, true)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Transaction has changed during signing")); + signing_abort(); + return false; } memcpy(&node, &root, sizeof(HDNode)); @@ -953,6 +953,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, tx_weight = 4 * size; + foreign_address_confirmed = false; taproot_only = true; signatures = 0; idx1 = 0; @@ -1377,10 +1378,22 @@ static bool signing_add_input(TxInputType *txinput) { return false; } - if (!fsm_checkCoinPath(coin, txinput->script_type, txinput->address_n_count, - txinput->address_n, txinput->has_multisig, true)) { - signing_abort(); - return false; + if (txinput->script_type != InputScriptType_EXTERNAL && + !coin_path_check(coin, txinput->script_type, txinput->address_n_count, + txinput->address_n, txinput->has_multisig, true)) { + if (config_getSafetyCheckLevel() == SafetyCheckLevel_Strict && + !coin_path_check(coin, txinput->script_type, txinput->address_n_count, + txinput->address_n, txinput->has_multisig, false)) { + fsm_sendFailure(FailureType_Failure_DataError, _("Forbidden key path")); + signing_abort(); + return false; + } + + if (!fsm_layoutPathWarning()) { + signing_abort(); + return false; + } + foreign_address_confirmed = true; } if (!fill_input_script_pubkey(coin, &root, txinput)) { diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 726dcdeb7..e06b72b3e 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -137,7 +137,7 @@ "T1_bitcoin-test_komodo.py::test_one_one_rewards_claim": "d6ba8441ad5e4bbdb191eef24fd679637e468cf1e7317b290bf89d2588bea214", "T1_bitcoin-test_multisig.py::test_15_of_15": "ba0a7e6d6a6f37bf553130acc7aa2471d9d7d804f1564837f149b3b5ecec0461", "T1_bitcoin-test_multisig.py::test_2_of_3": "4ece08d5a19590a521e22aae038a492796922f26bb8ba70614211a6ade5bce18", -"T1_bitcoin-test_multisig.py::test_attack_change_input": "f4f75000bfc3af0006a767e9afbc7f3930bc6bad864ca0d31656735d4103bddc", +"T1_bitcoin-test_multisig.py::test_attack_change_input": "b5beb346018c89e34a219b5466e3f2f257865b8623c356e2b249742d89e04da3", "T1_bitcoin-test_multisig.py::test_missing_pubkey": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_multisig_change.py::test_external_external": "b31515c4102fe602ed1e951bf67db483ffb8874dacc4b0359e9ef67d16999178", "T1_bitcoin-test_multisig_change.py::test_external_internal": "ceef2445ab95ec10543e320224b13febef2428d240cb01c58dd7ce878b121997", @@ -255,7 +255,7 @@ "T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail_asap": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_pass_forkid": "c83cf4f8324514dba0831e96fa2c20c30cef4121dcd594cf3232af19e4721a07", -"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_prompt": "0603601df63d976ca01ee3428d3f18f908695f500bb0c81e33483edd164b60f7", +"T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_prompt": "cbf1b6f66151a120689757e6dcd7af9483ceb19e5aa1dff3e1fb5c6f4be8d292", "T1_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_inputs": "5b980d57e7d1707d8802bff0665e0460fe5c594c91d758b05ee59020b72e3941", "T1_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_non_segwit_inputs": "704181fd5aa2ff33a9e5a27874187585ef946f7cdf6e690a7316a33921f25602", "T1_bitcoin-test_signtx_mixed_inputs.py::test_segwit_non_segwit_inputs": "5b980d57e7d1707d8802bff0665e0460fe5c594c91d758b05ee59020b72e3941", From 2b401f48f8b4b147876eda7637a86457e03906ac Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Tue, 15 Mar 2022 15:07:06 +0100 Subject: [PATCH 18/32] feat(legacy): Warn only once about non-standard paths. [no changelog] --- legacy/firmware/signing.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index 7fb241726..817a9fbd6 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -1389,11 +1389,13 @@ static bool signing_add_input(TxInputType *txinput) { return false; } - if (!fsm_layoutPathWarning()) { - signing_abort(); - return false; + if (!foreign_address_confirmed) { + if (!fsm_layoutPathWarning()) { + signing_abort(); + return false; + } + foreign_address_confirmed = true; } - foreign_address_confirmed = true; } if (!fill_input_script_pubkey(coin, &root, txinput)) { From 29304857b531d7bfc93a13df893acfbde67ac558 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 18 Mar 2022 16:53:44 +0100 Subject: [PATCH 19/32] feat(legacy): Warn about unverified external inputs. --- legacy/firmware/layout2.c | 7 +++++++ legacy/firmware/layout2.h | 1 + legacy/firmware/signing.c | 17 +++++++++++++++++ tests/ui_tests/fixtures.json | 4 ++-- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/legacy/firmware/layout2.c b/legacy/firmware/layout2.c index 3c75f9784..ff1d68d50 100644 --- a/legacy/firmware/layout2.c +++ b/legacy/firmware/layout2.c @@ -598,6 +598,13 @@ void layoutChangeCountOverThreshold(uint32_t change_count) { _("Continue?"), NULL); } +void layoutConfirmUnverifiedExternalInputs(void) { + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, + _("Warning!"), _("The transaction"), + _("contains unverified"), _("external inputs."), + _("Continue?"), NULL); +} + void layoutConfirmNondefaultLockTime(uint32_t lock_time, bool lock_time_disabled) { if (lock_time_disabled) { diff --git a/legacy/firmware/layout2.h b/legacy/firmware/layout2.h index 428d72562..ede148617 100644 --- a/legacy/firmware/layout2.h +++ b/legacy/firmware/layout2.h @@ -68,6 +68,7 @@ void layoutConfirmModifyFee(const CoinInfo *coin, AmountUnit amount_unit, void layoutFeeOverThreshold(const CoinInfo *coin, AmountUnit amount_unit, uint64_t fee); void layoutChangeCountOverThreshold(uint32_t change_count); +void layoutConfirmUnverifiedExternalInputs(void); void layoutConfirmNondefaultLockTime(uint32_t lock_time, bool lock_time_disabled); void layoutVerifyAddress(const CoinInfo *coin, const char *address); diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index 817a9fbd6..c68bb2faf 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -341,6 +341,14 @@ static bool is_external_input(uint32_t i) { return external_inputs[i / 32] & (1 << (i % 32)); } +static bool has_external_input(void) { + uint32_t sum = 0; + for (size_t i = 0; i < sizeof(external_inputs) / sizeof(uint32_t); ++i) { + sum |= external_inputs[i]; + } + return sum != 0; +} + void send_req_1_input(void) { signing_stage = STAGE_REQUEST_1_INPUT; resp.has_request_type = true; @@ -1803,6 +1811,15 @@ static bool signing_add_orig_output(TxOutputType *orig_output) { } static bool signing_confirm_tx(void) { + if (has_external_input()) { + layoutConfirmUnverifiedExternalInputs(); + if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) { + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); + signing_abort(); + return false; + } + } + if (coin->negative_fee) { // bypass check for negative fee coins, required for reward TX } else { diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index e06b72b3e..14d664012 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -249,8 +249,8 @@ "T1_bitcoin-test_signtx_amount_unit.py::test_signtx[AmountUnit.MILLIBITCOIN]": "8081910bd937c704fb65226dc85e8fc58a7331102aa036a5a97652638a0bde20", "T1_bitcoin-test_signtx_amount_unit.py::test_signtx[AmountUnit.SATOSHI]": "a565b50e63776aad284c42c71bf53e5844dff12f159cbd00679b97d2fb74fd20", "T1_bitcoin-test_signtx_amount_unit.py::test_signtx[None]": "367fd3c75f30f7224435e3309562d210d9ac6809ce2fae392f7fe75070fda094", -"T1_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "9640b4d0bdcde8fec8a4c077e1d12da211d02989458ad34115731237b3dad4f9", -"T1_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "c478ef5c111b38c0fee1f79df1e0d00ecd5c0e81913e59051047cb0db65ece69", +"T1_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "e09b404a39a4594f1b7bdc146bc6b8783f62f6c4568785f1ee8e1eae2d902c65", +"T1_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "3502ca6c3112b694161713d573a5547d3801894a990c108096900b95f689a734", "T1_bitcoin-test_signtx_invalid_path.py::test_attack_path_segwit": "473636ae4c43d8a349db09187b74eb4c1aa2b7fe02742d5fa928cdbc2a9e4cfd", "T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail_asap": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", From 9bce1536236567b24f07adacdcc34f9e4adb202a Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 18 Mar 2022 16:55:42 +0100 Subject: [PATCH 20/32] feat(core): Warn about unverified external inputs. --- core/src/apps/bitcoin/sign_tx/approvers.py | 5 +++++ core/src/apps/bitcoin/sign_tx/helpers.py | 9 +++++++++ core/src/apps/bitcoin/sign_tx/layout.py | 10 ++++++++++ tests/ui_tests/fixtures.json | 4 ++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/core/src/apps/bitcoin/sign_tx/approvers.py b/core/src/apps/bitcoin/sign_tx/approvers.py index c21943d3b..76cb172dc 100644 --- a/core/src/apps/bitcoin/sign_tx/approvers.py +++ b/core/src/apps/bitcoin/sign_tx/approvers.py @@ -50,6 +50,7 @@ class Approver: self.orig_change_out = 0 # sum of original change output amounts self.amount_unit = tx.amount_unit + self.has_unverified_external_input = False def is_payjoin(self) -> bool: # A PayJoin is a replacement transaction which manipulates the external inputs of the @@ -73,6 +74,7 @@ class Approver: self.orig_total_in += txi.amount if input_is_external_unverified(txi): + self.has_unverified_external_input = True if safety_checks.is_strict(): raise wire.ProcessError("Unverifiable external input.") else: @@ -235,6 +237,9 @@ class BasicApprover(Approver): async def approve_tx(self, tx_info: TxInfo, orig_txs: list[OriginalTxInfo]) -> None: await super().approve_tx(tx_info, orig_txs) + if self.has_unverified_external_input: + await helpers.confirm_unverified_external_input() + fee = self.total_in - self.total_out # some coins require negative fees for reward TX diff --git a/core/src/apps/bitcoin/sign_tx/helpers.py b/core/src/apps/bitcoin/sign_tx/helpers.py index 0b17301fa..f981ee4bc 100644 --- a/core/src/apps/bitcoin/sign_tx/helpers.py +++ b/core/src/apps/bitcoin/sign_tx/helpers.py @@ -180,6 +180,11 @@ class UiConfirmChangeCountOverThreshold(UiConfirm): return layout.confirm_change_count_over_threshold(ctx, self.change_count) +class UiConfirmUnverifiedExternalInput(UiConfirm): + def confirm_dialog(self, ctx: wire.Context) -> Awaitable[Any]: + return layout.confirm_unverified_external_input(ctx) + + class UiConfirmForeignAddress(UiConfirm): def __init__(self, address_n: list): self.address_n = address_n @@ -239,6 +244,10 @@ def confirm_change_count_over_threshold(change_count: int) -> Awaitable[Any]: # return (yield UiConfirmChangeCountOverThreshold(change_count)) +def confirm_unverified_external_input() -> Awaitable[Any]: # type: ignore [awaitable-is-generator] + return (yield UiConfirmUnverifiedExternalInput()) + + def confirm_foreign_address(address_n: list) -> Awaitable[Any]: # type: ignore [awaitable-is-generator] return (yield UiConfirmForeignAddress(address_n)) diff --git a/core/src/apps/bitcoin/sign_tx/layout.py b/core/src/apps/bitcoin/sign_tx/layout.py index 1c2a0e5b0..910a826ff 100644 --- a/core/src/apps/bitcoin/sign_tx/layout.py +++ b/core/src/apps/bitcoin/sign_tx/layout.py @@ -220,6 +220,16 @@ async def confirm_change_count_over_threshold( ) +async def confirm_unverified_external_input(ctx: wire.Context) -> None: + await layouts.confirm_metadata( + ctx, + "unverified_external_input", + "Warning", + "The transaction contains unverified external inputs.", + br_code=ButtonRequestType.SignTx, + ) + + async def confirm_nondefault_locktime( ctx: wire.Context, lock_time: int, lock_time_disabled: bool ) -> None: diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 14d664012..a8c3b2a98 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -898,9 +898,9 @@ "TT_bitcoin-test_signtx_external.py::test_p2pkh_presigned": "8dd8089941ceb0d82c9425c69d54240f99e3ae7932ef24acd49313d28389b683", "TT_bitcoin-test_signtx_external.py::test_p2pkh_with_proof": "c09de07fbbf1e047442180e2facb5482d06a1a428891b875b7dd93c9e4704ae1", "TT_bitcoin-test_signtx_external.py::test_p2tr_external_presigned": "c714c4a4ea8b98dfbdd8185925adafbafc62570f415688972d6003a19d7b4d23", -"TT_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "9919d854e2702be375ad09c74af4fbaaa92d36cc2ed360cc7cfbd196c21a39a6", +"TT_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "b398085c2fa6d4fa1ba97d872f95f3ac2268e9455f5831344f6e34a4badf7a17", "TT_bitcoin-test_signtx_external.py::test_p2tr_with_proof": "d6723e2243bc38231ec4eb9ed63afd39610460c0d859b4c576b12db1f7915d02", -"TT_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "7780f69c321c49c97ee970617ba91a63a7c375dd5ca3d13dec943c28511fb128", +"TT_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "d178bd3e2cadbe0992904b3d32df963b75e1da801804a471e45a1c5c0a9f2581", "TT_bitcoin-test_signtx_external.py::test_p2wpkh_in_p2sh_presigned": "8313bff77e41aef142c3b25818ab58dcc7e9d658d38e2e8fc50629ebbe05869b", "TT_bitcoin-test_signtx_external.py::test_p2wpkh_in_p2sh_with_proof": "c09de07fbbf1e047442180e2facb5482d06a1a428891b875b7dd93c9e4704ae1", "TT_bitcoin-test_signtx_external.py::test_p2wpkh_presigned": "4608478b1d61415cf0ec93a0ea4397c35d17a91d4b6d25e9c024b77330e398eb", From d16b44bad62810224d028fc78d8dd7d25c733cbd Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 18 Mar 2022 20:47:52 +0100 Subject: [PATCH 21/32] feat(core): Verify signatures of all original inputs in replacement transactions. --- core/src/apps/bitcoin/sign_tx/bitcoin.py | 60 ++++++++++--------- core/src/apps/bitcoin/sign_tx/tx_info.py | 17 ++---- docs/common/communication/bitcoin-signing.md | 6 +- .../bitcoin/test_signtx_replacement.py | 13 ++++ ...39e95efb0803071648048a7f289492e7b4c8a.json | 1 + ...6bab4955707cd216011d918b526f5e86d85ba.json | 3 +- ...7c7feae89fdde12867943eec91293139730d1.json | 1 + 7 files changed, 58 insertions(+), 43 deletions(-) diff --git a/core/src/apps/bitcoin/sign_tx/bitcoin.py b/core/src/apps/bitcoin/sign_tx/bitcoin.py index ec7321557..2acdefefc 100644 --- a/core/src/apps/bitcoin/sign_tx/bitcoin.py +++ b/core/src/apps/bitcoin/sign_tx/bitcoin.py @@ -122,9 +122,9 @@ class Bitcoin: # stable device tests. self.orig_txs: list[OriginalTxInfo] = [] - # The digests of the inputs streamed for approval in Step 1. These are used to ensure that - # the inputs streamed for verification in Step 3 are the same as those in Step 1. - self.h_inputs: bytes | None = None + # The digests of the external inputs streamed for approval in Step 1. These are used + # to ensure that the inputs streamed for verification in Step 3 are the same as + # those in Step 1. self.h_external_inputs: bytes | None = None # The index of the payment request being processed. @@ -165,11 +165,12 @@ class Bitcoin: if txi.orig_hash: await self.process_original_input(txi, script_pubkey) - self.h_inputs = self.tx_info.get_tx_check_digest() + self.tx_info.h_inputs_check = self.tx_info.get_tx_check_digest() self.h_external_inputs = h_external_inputs_check.get_digest() # Finalize original inputs. for orig in self.orig_txs: + orig.h_inputs_check = orig.get_tx_check_digest() if orig.index != orig.tx.inputs_count: raise wire.ProcessError("Removal of original inputs is not supported.") @@ -194,7 +195,7 @@ class Bitcoin: await orig.finalize_tx_hash() async def step3_verify_inputs(self) -> None: - # should come out the same as h_inputs, checked before continuing + # should come out the same as h_inputs_check, checked before continuing h_check = HashWriter(sha256()) if self.taproot_only: @@ -220,7 +221,7 @@ class Bitcoin: # inputs or to falsely claim that a transaction is a replacement of an already approved # transaction or to construct a valid transaction by combining signatures obtained in # multiple rounds of the attack. - expected_digest = self.h_inputs + expected_digest = self.tx_info.h_inputs_check for i in range(self.tx_info.tx.inputs_count): progress.advance() txi = await helpers.request_tx_input(self.tx_req, i, self.coin) @@ -406,29 +407,34 @@ class Bitcoin: async def verify_original_txs(self) -> None: for orig in self.orig_txs: - if orig.verification_input is None: - raise wire.ProcessError( - "Each original transaction must specify address_n for at least one input." + # should come out the same as h_inputs_check, checked before continuing + h_check = HashWriter(sha256()) + + for i in range(orig.tx.inputs_count): + txi = await helpers.request_tx_input( + self.tx_req, i, self.coin, orig.orig_hash + ) + writers.write_tx_input_check(h_check, txi) + script_pubkey = self.input_derive_script(txi) + verifier = SignatureVerifier( + script_pubkey, txi.script_sig, txi.witness, self.coin + ) + verifier.ensure_hash_type( + (SigHashType.SIGHASH_ALL_TAPROOT, self.get_sighash_type(txi)) ) + tx_digest = await self.get_tx_digest( + i, + txi, + orig, + verifier.public_keys, + verifier.threshold, + script_pubkey, + ) + verifier.verify(tx_digest) - assert orig.verification_index is not None - txi = orig.verification_input - script_pubkey = self.input_derive_script(txi) - verifier = SignatureVerifier( - script_pubkey, txi.script_sig, txi.witness, self.coin - ) - verifier.ensure_hash_type( - (SigHashType.SIGHASH_ALL_TAPROOT, self.get_sighash_type(txi)) - ) - tx_digest = await self.get_tx_digest( - orig.verification_index, - txi, - orig, - verifier.public_keys, - verifier.threshold, - script_pubkey, - ) - verifier.verify(tx_digest) + # check that the inputs were the same as those streamed for approval + if h_check.get_digest() != orig.h_inputs_check: + raise wire.ProcessError("Transaction has changed during signing") async def approve_output( self, diff --git a/core/src/apps/bitcoin/sign_tx/tx_info.py b/core/src/apps/bitcoin/sign_tx/tx_info.py index 8944f3a66..e91620e83 100644 --- a/core/src/apps/bitcoin/sign_tx/tx_info.py +++ b/core/src/apps/bitcoin/sign_tx/tx_info.py @@ -72,6 +72,11 @@ class TxInfoBase: # in Steps 1 and 2 and the ones streamed for signing legacy inputs in Step 4. self.h_tx_check = HashWriter(sha256()) # not a real tx hash + # The digests of the inputs streamed for approval in Step 1. These are used to + # ensure that the inputs streamed for verification in Step 3 are the same as + # those in Step 1. + self.h_inputs_check: bytes | None = None + # BIP-0143 transaction hashing. self.sig_hasher = signer.create_sig_hasher(tx) @@ -145,22 +150,10 @@ class OriginalTxInfo(TxInfoBase): signer.write_tx_header(self.h_tx, tx, witness_marker=False) writers.write_compact_size(self.h_tx, tx.inputs_count) - # The input which will be used for verification and its index in the original transaction. - self.verification_input: TxInput | None = None - self.verification_index: int | None = None - def add_input(self, txi: TxInput, script_pubkey: bytes) -> None: super().add_input(txi, script_pubkey) writers.write_tx_input(self.h_tx, txi, txi.script_sig or bytes()) - # For verification use the first original non-multisig input that specifies address_n. - # NOTE: Supporting replacement transactions where all internal inputs are multisig would - # require checking the signatures of all of the original internal inputs or not allowing - # unverified external inputs in transactions where multisig inputs are present. - if not self.verification_input and txi.address_n and not txi.multisig: - self.verification_input = txi - self.verification_index = self.index - def add_output(self, txo: TxOutput, script_pubkey: bytes) -> None: super().add_output(txo, script_pubkey) diff --git a/docs/common/communication/bitcoin-signing.md b/docs/common/communication/bitcoin-signing.md index 7054319d7..7b484e038 100644 --- a/docs/common/communication/bitcoin-signing.md +++ b/docs/common/communication/bitcoin-signing.md @@ -286,10 +286,10 @@ set to `tx.extra_data_chunk`. Trezor sets `request_type` to `TXORIGINPUT`. `request_details.tx_hash` is the transaction hash of the original transaction. -Host must respond with a `TxAckInput` message. All relevant data must be set in +The host must respond with a `TxAckInput` message. All relevant data must be set in `tx.input`. The derivation path and `script_type` are mandatory for all original -internal inputs. For each original transaction, one of its original internal inputs must -be accompanied with a valid signature in the `script_sig` and/or `witness` fields. +internal inputs. All original internal inputs must also be accompanied with full +transaction signature data in the `script_sig` and/or `witness` fields. ### Original transaction output diff --git a/tests/device_tests/bitcoin/test_signtx_replacement.py b/tests/device_tests/bitcoin/test_signtx_replacement.py index f9086221e..ea31895a3 100644 --- a/tests/device_tests/bitcoin/test_signtx_replacement.py +++ b/tests/device_tests/bitcoin/test_signtx_replacement.py @@ -133,6 +133,7 @@ def test_p2pkh_fee_bump(client: Client): request_meta(TXHASH_beafc7), request_input(0, TXHASH_beafc7), request_output(0, TXHASH_beafc7), + request_orig_input(0, TXHASH_50f6f1), (tt, request_orig_input(0, TXHASH_50f6f1)), (tt, request_orig_output(0, TXHASH_50f6f1)), (tt, request_orig_output(1, TXHASH_50f6f1)), @@ -257,6 +258,8 @@ def test_p2tr_fee_bump(client: Client): request_output(1), request_orig_output(1, TXHASH_8e4af7), messages.ButtonRequest(code=B.SignTx), + request_orig_input(0, TXHASH_8e4af7), + request_orig_input(1, TXHASH_8e4af7), request_input(0), request_input(1), request_output(0), @@ -328,6 +331,7 @@ def test_p2wpkh_finalize(client: Client): request_output(0, TXHASH_43d273), request_output(1, TXHASH_43d273), request_output(2, TXHASH_43d273), + request_orig_input(0, TXHASH_70f987), request_input(0), request_output(0), request_output(1), @@ -464,6 +468,7 @@ def test_p2wpkh_payjoin( request_input(0, TXHASH_70f987), request_output(0, TXHASH_70f987), request_output(1, TXHASH_70f987), + request_orig_input(0, TXHASH_65b768), request_input(0), request_input(1), request_output(0), @@ -538,6 +543,8 @@ def test_p2wpkh_in_p2sh_remove_change(client: Client): request_meta(TXHASH_efaa41), request_input(0, TXHASH_efaa41), request_output(0, TXHASH_efaa41), + request_orig_input(0, TXHASH_334cd7), + request_orig_input(1, TXHASH_334cd7), request_input(0), request_input(1), request_output(0), @@ -618,6 +625,8 @@ def test_p2wpkh_in_p2sh_fee_bump_from_external(client: Client): request_meta(TXHASH_efaa41), request_input(0, TXHASH_efaa41), request_output(0, TXHASH_efaa41), + request_orig_input(0, TXHASH_334cd7), + request_orig_input(1, TXHASH_334cd7), request_input(0), request_input(1), request_output(0), @@ -759,6 +768,10 @@ def test_tx_meld(client: Client): request_input(1, TXHASH_927784), request_input(2, TXHASH_927784), request_output(0, TXHASH_927784), + request_orig_input(0, TXHASH_334cd7), + request_orig_input(1, TXHASH_334cd7), + request_orig_input(0, TXHASH_ed89ac), + request_orig_input(1, TXHASH_ed89ac), request_input(0), request_input(1), request_input(2), diff --git a/tests/txcache/testnet/334cd7ad982b3b15d07dd1c84e939e95efb0803071648048a7f289492e7b4c8a.json b/tests/txcache/testnet/334cd7ad982b3b15d07dd1c84e939e95efb0803071648048a7f289492e7b4c8a.json index dbac3f2f8..f2afa38d0 100644 --- a/tests/txcache/testnet/334cd7ad982b3b15d07dd1c84e939e95efb0803071648048a7f289492e7b4c8a.json +++ b/tests/txcache/testnet/334cd7ad982b3b15d07dd1c84e939e95efb0803071648048a7f289492e7b4c8a.json @@ -17,6 +17,7 @@ "amount": 998060, "script_type": "SPENDP2SHWITNESS", "script_sig": "160014209297fb46272a0b7e05139440dbd39daea3e25a", + "witness":"0247304402206f5b2032601278685921b397416cecd5f70cde48b7203bf2a953283c0cd05f4002205fd21a2c318330f11e8433f8fae6b1c4c257a79da55be9712961214ba2752a1f012103c2c2e65556ca4b7371549324b99390725493c8a6792e093a0bdcbb3e2d7df4ab", "sequence": 4294967295 } ], diff --git a/tests/txcache/testnet/8e4af74cee65dac2615f7befea76bab4955707cd216011d918b526f5e86d85ba.json b/tests/txcache/testnet/8e4af74cee65dac2615f7befea76bab4955707cd216011d918b526f5e86d85ba.json index c7daeb3d0..53cb26d4f 100644 --- a/tests/txcache/testnet/8e4af74cee65dac2615f7befea76bab4955707cd216011d918b526f5e86d85ba.json +++ b/tests/txcache/testnet/8e4af74cee65dac2615f7befea76bab4955707cd216011d918b526f5e86d85ba.json @@ -17,7 +17,8 @@ "prev_index": 0, "script_sig": "", "script_type": "SPENDTAPROOT", - "sequence": 4294967293 + "sequence": 4294967293, + "witness": "0140d961a3fc97561c8a305d0ba78488e8d1efed520ac36b226db76277c38e5ab112236a2f821b6dde82dc4013f74148d1ec6e1e471b952755b5265b7ed594afb723" } ], "lock_time": 0, diff --git a/tests/txcache/testnet/ed89acb52cfa438e3653007478e7c7feae89fdde12867943eec91293139730d1.json b/tests/txcache/testnet/ed89acb52cfa438e3653007478e7c7feae89fdde12867943eec91293139730d1.json index b780aa60e..60f3a0369 100644 --- a/tests/txcache/testnet/ed89acb52cfa438e3653007478e7c7feae89fdde12867943eec91293139730d1.json +++ b/tests/txcache/testnet/ed89acb52cfa438e3653007478e7c7feae89fdde12867943eec91293139730d1.json @@ -27,6 +27,7 @@ "amount": 839318869, "script_type": "SPENDP2SHWITNESS", "script_sig": "160014681ea49259abb892460bf3373e8a0b43d877fa18", + "witness": "02473044022039bb1710e041e9a936bd3adf39f61906ac4363a67d1c29b1a264ff8cf5a0c95102202829307d82141792125480abe6491f0f0c7d675c3d1a06daa383d617afcb53380121028cbc37e1816a23086fa738c8415def477e813e20f484dbbd6f5a33a37c322251", "sequence": 4294967295 } ], From 706b74aaebc3072308c2ca1ee2a2fc821cc46898 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Tue, 22 Mar 2022 16:24:44 +0100 Subject: [PATCH 22/32] refactor(legacy): Transaction checksum in Bitcoin signing. --- legacy/firmware/signing.c | 118 ++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 48 deletions(-) diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index c68bb2faf..9f37150aa 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -94,16 +94,15 @@ static uint8_t sig[64]; // Used in Phase 1 to store signature of original tx #if !BITCOIN_ONLY static uint8_t decred_hash_prefix[32]; #endif -static uint8_t hash_inputs_check[32]; static uint64_t total_in, total_out, change_out; static uint64_t orig_total_in, orig_total_out, orig_change_out; -static uint32_t next_legacy_input; static uint32_t progress, progress_step, progress_meta_step; static uint32_t tx_weight; typedef struct { uint32_t inputs_count; uint32_t outputs_count; + uint32_t next_legacy_input; uint32_t min_sequence; bool multisig_fp_set; bool multisig_fp_mismatch; @@ -119,11 +118,13 @@ typedef struct { uint32_t branch_id; uint8_t hash_header[32]; #endif + Hasher hasher_check; Hasher hasher_prevouts; Hasher hasher_amounts; Hasher hasher_scriptpubkeys; Hasher hasher_sequences; Hasher hasher_outputs; + uint8_t hash_inputs_check[32]; uint8_t hash_prevouts[32]; uint8_t hash_amounts[32]; uint8_t hash_scriptpubkeys[32]; @@ -217,6 +218,7 @@ Phase1 - process inputs - check previous transactions ========================================================= +Stage 1: Get inputs and optionally get original inputs. foreach I (idx1): Request I STAGE_REQUEST_1_INPUT Add I to segwit sub-hashes @@ -226,9 +228,11 @@ foreach I (idx1): Request input I2 orig_hash, orig_index STAGE_REQUEST_1_ORIG_INPUT Check I matches I2 Add I2 to original segwit sub-hashes + Add I2 to orig_hash_inputs_check if (Decred) Return I +Stage 2: Get outputs and optionally get original outputs. foreach O (idx1): Request O STAGE_REQUEST_2_OUTPUT Add O to Decred decred_hash_prefix @@ -246,8 +250,10 @@ foreach O (idx1): Check tx fee Ask for confirmation +Stage 3: Check transaction. + if (taproot_only) - Skip to Phase 2. + Skip checking of previous transactions. foreach I (idx1): Request I STAGE_REQUEST_3_INPUT @@ -514,7 +520,7 @@ void send_req_4_output(void) { msg_write(MessageType_MessageType_TxRequest, &resp); } -void send_req_segwit_input(void) { +void send_req_nonlegacy_input(void) { signing_stage = STAGE_REQUEST_NONLEGACY_INPUT; resp.has_request_type = true; resp.request_type = RequestType_TXINPUT; @@ -569,7 +575,6 @@ void phase1_request_next_input(void) { idx1++; send_req_1_input(); } else { - hasher_Final(&hasher_check, hash_inputs_check); idx1 = 0; if (is_replacement) { @@ -637,11 +642,11 @@ void phase1_request_orig_input(void) { } void phase2_request_next_input(void) { - if (idx1 == next_legacy_input) { + if (idx1 == info.next_legacy_input) { idx2 = 0; send_req_4_input(); } else { - send_req_segwit_input(); + send_req_nonlegacy_input(); } } @@ -832,6 +837,7 @@ static bool tx_info_init(TxInfo *tx_info, uint32_t inputs_count, tx_info->inputs_count = inputs_count; tx_info->outputs_count = outputs_count; + tx_info->next_legacy_input = 0xffffffff; tx_info->min_sequence = SEQUENCE_FINAL; tx_info->multisig_fp_set = false; tx_info->multisig_fp_mismatch = false; @@ -892,6 +898,8 @@ static bool tx_info_init(TxInfo *tx_info, uint32_t inputs_count, } #endif + hasher_Init(&tx_info->hasher_check, HASHER_SHA2); + #if !BITCOIN_ONLY if (coin->overwintered) { if (tx_info->version == 5) { @@ -985,8 +993,6 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, // this means 50 % per phase. progress_step = (500 << PROGRESS_PRECISION) / info.inputs_count; - next_legacy_input = 0xffffffff; - uint32_t branch_id = 0; #if !BITCOIN_ONLY branch_id = info.branch_id; @@ -1348,6 +1354,7 @@ static void txinfo_fill_zip244_header_hash(TxInfo *tx_info) { #endif static void tx_info_finish(TxInfo *tx_info) { + hasher_Final(&tx_info->hasher_check, tx_info->hash_inputs_check); hasher_Final(&tx_info->hasher_prevouts, tx_info->hash_prevouts); hasher_Final(&tx_info->hasher_amounts, tx_info->hash_amounts); hasher_Final(&tx_info->hasher_scriptpubkeys, tx_info->hash_scriptpubkeys); @@ -1377,9 +1384,33 @@ static void tx_info_finish(TxInfo *tx_info) { #endif } +static bool tx_info_check_inputs_hash(TxInfo *tx_info) { + uint8_t hash[32]; + hasher_Final(&tx_info->hasher_check, hash); + if (memcmp(hash, tx_info->hash_inputs_check, 32) != 0) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Transaction has changed during signing")); + signing_abort(); + return false; + } + return true; +} + +static bool tx_info_check_outputs_hash(TxInfo *tx_info) { + uint8_t hash[32] = {0}; + hasher_Final(&tx_info->hasher_check, hash); + if (memcmp(hash, tx_info->hash_outputs, 32) != 0) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Transaction has changed during signing")); + signing_abort(); + return false; + } + return true; +} + static bool signing_add_input(TxInputType *txinput) { // hash all input data to check it later (relevant for fee computation) - if (!tx_input_check_hash(&hasher_check, txinput)) { + if (!tx_input_check_hash(&info.hasher_check, txinput)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to hash input")); signing_abort(); @@ -1448,11 +1479,7 @@ static bool signing_check_prevtx_hash(void) { idx1++; send_req_3_input(); } else { - hasher_Final(&hasher_check, hash); - if (memcmp(hash, hash_inputs_check, 32) != 0) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Transaction has changed during signing")); - signing_abort(); + if (!tx_info_check_inputs_hash(&info)) { return false; } @@ -2396,17 +2423,12 @@ static bool signing_sign_bip340(const uint8_t *private_key, } static bool signing_sign_legacy_input(void) { - uint8_t hash[32] = {0}; - hasher_Final(&hasher_check, hash); - if (memcmp(hash, info.hash_outputs, 32) != 0 || taproot_only) { - fsm_sendFailure(FailureType_Failure_ProcessError, - _("Transaction has changed during signing")); - signing_abort(); - return false; - } - + // Finalize legacy digest computation. uint32_t hash_type = signing_hash_type(&input); hasher_Update(&ti.hasher, (const uint8_t *)&hash_type, 4); + + // Compute the digest and generate signature. + uint8_t hash[32] = {0}; tx_hash_final(&ti, hash, false); resp.has_serialized = true; if (!signing_sign_ecdsa(&input, privkey, pubkey, hash)) return false; @@ -2612,7 +2634,9 @@ void signing_txack(TransactionType *tx) { if (!coin->force_bip143 && !coin->overwintered) { // remember the first non-segwit input -- this is the first input // we need to sign during phase2 - if (next_legacy_input == 0xffffffff) next_legacy_input = idx1; + if (info.next_legacy_input == 0xffffffff) { + info.next_legacy_input = idx1; + } } } else if (is_segwit_input_script_type(&tx->inputs[0])) { if (!to.is_segwit) { @@ -2764,27 +2788,28 @@ void signing_txack(TransactionType *tx) { return; #endif case STAGE_REQUEST_3_INPUT: - if (!signing_validate_input(&tx->inputs[0])) { - return; + if (idx1 == 0) { + hasher_Reset(&info.hasher_check); } - if (!tx->inputs[0].has_amount) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Expected input with amount")); - signing_abort(); + if (!signing_validate_input(tx->inputs)) { return; } - if (idx1 == 0) { - hasher_Reset(&hasher_check); - } - if (!tx_input_check_hash(&hasher_check, tx->inputs)) { + if (!tx_input_check_hash(&info.hasher_check, tx->inputs)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to hash input")); signing_abort(); return; } + if (!tx->inputs[0].has_amount) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Expected input with amount")); + signing_abort(); + return; + } + memcpy(&input, tx->inputs, sizeof(TxInputType)); if (!fill_input_script_pubkey(coin, &root, &input)) { @@ -2987,10 +3012,10 @@ void signing_txack(TransactionType *tx) { info.lock_time, info.expiry, tx->branch_id, 0, coin->curve->hasher_sign, coin->overwintered, info.version_group_id, info.timestamp); - hasher_Reset(&hasher_check); + hasher_Reset(&info.hasher_check); } // check inputs are the same as those in phase 1 - if (!tx_input_check_hash(&hasher_check, tx->inputs)) { + if (!tx_input_check_hash(&info.hasher_check, tx->inputs)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to hash input")); signing_abort(); @@ -3006,10 +3031,10 @@ void signing_txack(TransactionType *tx) { memcpy(privkey, node.private_key, 32); memcpy(pubkey, node.public_key, 33); } else { - if (next_legacy_input == idx1 && idx2 > idx1 && + if (info.next_legacy_input == idx1 && idx2 > idx1 && (tx->inputs[0].script_type == InputScriptType_SPENDADDRESS || tx->inputs[0].script_type == InputScriptType_SPENDMULTISIG)) { - next_legacy_input = idx2; + info.next_legacy_input = idx2; } tx->inputs[0].script_sig.size = 0; } @@ -3023,15 +3048,11 @@ void signing_txack(TransactionType *tx) { idx2++; send_req_4_input(); } else { - uint8_t hash[32] = {0}; - hasher_Final(&hasher_check, hash); - if (memcmp(hash, hash_inputs_check, 32) != 0) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Transaction has changed during signing")); - signing_abort(); + if (!tx_info_check_inputs_hash(&info)) { return; } - hasher_Reset(&hasher_check); + + hasher_Reset(&info.hasher_check); idx2 = 0; send_req_4_output(); } @@ -3051,7 +3072,7 @@ void signing_txack(TransactionType *tx) { return; } // check hashOutputs - tx_output_hash(&hasher_check, &bin_output, coin->decred); + tx_output_hash(&info.hasher_check, &bin_output, coin->decred); if (!tx_serialize_output_hash(&ti, &bin_output)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize output")); @@ -3062,7 +3083,8 @@ void signing_txack(TransactionType *tx) { idx2++; send_req_4_output(); } else { - if (!signing_sign_legacy_input()) { + if (!tx_info_check_outputs_hash(&info) || + !signing_sign_legacy_input()) { return; } // since this took a longer time, update progress From 903fa9b471f7b672446956389b8855af6d71d1c9 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Tue, 22 Mar 2022 16:32:57 +0100 Subject: [PATCH 23/32] feat(legacy): Verify signatures of all original internal inputs in replacement transactions. --- legacy/firmware/signing.c | 474 ++++++++++++++---- .../bitcoin/test_signtx_replacement.py | 6 +- tests/ui_tests/fixtures.json | 4 +- 3 files changed, 376 insertions(+), 108 deletions(-) diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index 9f37150aa..f18100cad 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -57,6 +57,9 @@ enum { #if !BITCOIN_ONLY STAGE_REQUEST_3_PREV_EXTRADATA, #endif + STAGE_REQUEST_3_ORIG_INPUT, + STAGE_REQUEST_3_ORIG_OUTPUT, + STAGE_REQUEST_3_ORIG_NONLEGACY_INPUT, STAGE_REQUEST_4_INPUT, STAGE_REQUEST_4_OUTPUT, STAGE_REQUEST_NONLEGACY_INPUT, @@ -138,10 +141,7 @@ typedef struct { static TxInfo info; /* Variables specific to replacement transactions. */ -static bool is_replacement; // Is this a replacement transaction? -static bool have_orig_verif_input; // Is orig_verif_input, sig and node set? -static uint32_t orig_verif_input_idx; // Index of orig_verif_input in orig tx. -static TxInputType orig_verif_input; // The input for signature verification. +static bool is_replacement; // Is this a replacement transaction? static TxInfo orig_info; static uint8_t orig_hash[32]; // TXID of the original transaction. @@ -228,7 +228,7 @@ foreach I (idx1): Request input I2 orig_hash, orig_index STAGE_REQUEST_1_ORIG_INPUT Check I matches I2 Add I2 to original segwit sub-hashes - Add I2 to orig_hash_inputs_check + Add I2 to orig_info.hash_inputs_check if (Decred) Return I @@ -266,6 +266,34 @@ foreach I (idx1): Request prevhash extra data (if applicable) STAGE_REQUEST_3_PREV_EXTRADATA Calculate hash of streamed tx, compare to prevhash I +if (is_replacement) + foreach orig I (idx1): + if (orig idx1 is not legacy) + Request input I, orig_hash, idx1 STAGE_REQUEST_3_ORIG_NONLEGACY_INPUT + Add I to OuterTransactionChecksum + Verify signature of I if I is internal + else + foreach orig I (idx2): + Request input I, orig_hash, idx2 STAGE_REQUEST_3_ORIG_INPUT + Add I to InnerTransactionChecksum + Add I to LegacyTransactionDigest + if idx1 == idx2 + Add I to OuterTransactionChecksum + Save signature for verification + + Ensure InnerTransactionChecksum matches orig_info.hash_inputs_check + + foreach orig O (idx2): + Request output O, orig_hash, idx2 STAGE_REQUEST_3_ORIG_OUTPUT + Add O to InnerTransactionChecksum + Add O to LegacyTransactionDigest + + Ensure InnerTransactionChecksum matches orig_hash_outputs + Verify signature of LegacyTransactionDigest + +Ensure OuterTransactionChecksum matches orig_info.hash_inputs_check + + Phase2: sign inputs, check that nothing changed =============================================== @@ -371,9 +399,8 @@ void send_req_1_orig_meta(void) { resp.request_type = RequestType_TXMETA; resp.has_details = true; resp.details.has_tx_hash = true; - resp.details.tx_hash.size = input.orig_hash.size; - memcpy(resp.details.tx_hash.bytes, input.orig_hash.bytes, - resp.details.tx_hash.size); + resp.details.tx_hash.size = sizeof(orig_hash); + memcpy(resp.details.tx_hash.bytes, orig_hash, resp.details.tx_hash.size); msg_write(MessageType_MessageType_TxRequest, &resp); } @@ -385,9 +412,8 @@ void send_req_1_orig_input(void) { resp.details.has_request_index = true; resp.details.request_index = idx2; resp.details.has_tx_hash = true; - resp.details.tx_hash.size = input.orig_hash.size; - memcpy(resp.details.tx_hash.bytes, input.orig_hash.bytes, - resp.details.tx_hash.size); + resp.details.tx_hash.size = sizeof(orig_hash); + memcpy(resp.details.tx_hash.bytes, orig_hash, resp.details.tx_hash.size); msg_write(MessageType_MessageType_TxRequest, &resp); } @@ -409,9 +435,8 @@ void send_req_2_orig_output(void) { resp.details.has_request_index = true; resp.details.request_index = idx2; resp.details.has_tx_hash = true; - resp.details.tx_hash.size = output.orig_hash.size; - memcpy(resp.details.tx_hash.bytes, output.orig_hash.bytes, - resp.details.tx_hash.size); + resp.details.tx_hash.size = sizeof(orig_hash); + memcpy(resp.details.tx_hash.bytes, orig_hash, resp.details.tx_hash.size); msg_write(MessageType_MessageType_TxRequest, &resp); } @@ -500,6 +525,45 @@ void send_req_3_prev_extradata(uint32_t chunk_offset, uint32_t chunk_len) { } #endif +void send_req_3_orig_nonlegacy_input(void) { + signing_stage = STAGE_REQUEST_3_ORIG_NONLEGACY_INPUT; + resp.has_request_type = true; + resp.request_type = RequestType_TXORIGINPUT; + resp.has_details = true; + resp.details.has_request_index = true; + resp.details.request_index = idx1; + resp.details.has_tx_hash = true; + resp.details.tx_hash.size = sizeof(orig_hash); + memcpy(resp.details.tx_hash.bytes, orig_hash, resp.details.tx_hash.size); + msg_write(MessageType_MessageType_TxRequest, &resp); +} + +void send_req_3_orig_input(void) { + signing_stage = STAGE_REQUEST_3_ORIG_INPUT; + resp.has_request_type = true; + resp.request_type = RequestType_TXORIGINPUT; + resp.has_details = true; + resp.details.has_request_index = true; + resp.details.request_index = idx2; + resp.details.has_tx_hash = true; + resp.details.tx_hash.size = sizeof(orig_hash); + memcpy(resp.details.tx_hash.bytes, orig_hash, resp.details.tx_hash.size); + msg_write(MessageType_MessageType_TxRequest, &resp); +} + +void send_req_3_orig_output(void) { + signing_stage = STAGE_REQUEST_3_ORIG_OUTPUT; + resp.has_request_type = true; + resp.request_type = RequestType_TXORIGOUTPUT; + resp.has_details = true; + resp.details.has_request_index = true; + resp.details.request_index = idx2; + resp.details.has_tx_hash = true; + resp.details.tx_hash.size = sizeof(orig_hash); + memcpy(resp.details.tx_hash.bytes, orig_hash, resp.details.tx_hash.size); + msg_write(MessageType_MessageType_TxRequest, &resp); +} + void send_req_4_input(void) { signing_stage = STAGE_REQUEST_4_INPUT; resp.has_request_type = true; @@ -650,6 +714,36 @@ void phase2_request_next_input(void) { } } +void phase2_request_orig_input(void) { + if (idx1 < orig_info.inputs_count) { + if (idx1 == 0) { + // Reset outer transaction check. + hasher_Reset(&hasher_check); + } + + if (idx1 == orig_info.next_legacy_input) { + idx2 = 0; + send_req_3_orig_input(); + } else { + send_req_3_orig_nonlegacy_input(); + } + } else { + // Ensure that the original transaction inputs haven't changed for the outer + // transaction check. + uint8_t hash[32]; + hasher_Final(&hasher_check, hash); + if (memcmp(hash, orig_info.hash_inputs_check, 32) != 0) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Transaction has changed during signing")); + signing_abort(); + return; + } + + idx1 = 0; + phase2_request_next_input(); + } +} + static bool extract_input_multisig_fp(TxInfo *tx_info, const TxInputType *txinput) { if (txinput->has_multisig && !tx_info->multisig_fp_mismatch) { @@ -985,8 +1079,6 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, memzero(&output, sizeof(TxOutputType)); memzero(&resp, sizeof(TxRequest)); is_replacement = false; - have_orig_verif_input = false; - orig_verif_input_idx = 0xffffffff; signing = true; progress = 0; // we step by 500/inputs_count per input in phase1 and phase2 @@ -1495,7 +1587,13 @@ static bool signing_check_prevtx_hash(void) { } else #endif { - phase2_request_next_input(); + if (is_replacement) { + // Verify original transaction. + phase2_request_orig_input(); + } else { + // Proceed to transaction signing. + phase2_request_next_input(); + } } } @@ -1643,6 +1741,14 @@ static bool save_signature(TxInputType *txinput) { } static bool signing_add_orig_input(TxInputType *orig_input) { + // hash all input data to check it later + if (!tx_input_check_hash(&orig_info.hasher_check, orig_input)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to hash input")); + signing_abort(); + return false; + } + if (!fill_input_script_pubkey(coin, &root, orig_input)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to derive scriptPubKey")); @@ -1681,7 +1787,7 @@ static bool signing_add_orig_input(TxInputType *orig_input) { return false; } - // Add input to original TXID computation before script_sig is overwritten. + // Add input to original TXID computation. if (!tx_serialize_input_hash(&tp, orig_input)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize input")); @@ -1689,44 +1795,13 @@ static bool signing_add_orig_input(TxInputType *orig_input) { return false; } - // The first original non-multisig input that has address_n set and a - // signature gets chosen as the verification input. Set script_sig for legacy - // digest computation. - // NOTE: Supporting replacement transactions where all internal inputs are - // multisig would require checking the signatures of all of the original - // internal inputs or not allowing unverified external inputs in transactions - // where multisig inputs are present. - if (!have_orig_verif_input && orig_input->address_n_count != 0 && - !orig_input->has_multisig && - ((orig_input->has_script_sig && orig_input->script_sig.size != 0) || - (orig_input->has_witness && orig_input->witness.size > 1))) { - // Save the signature before script_sig is overwritten. - if (!save_signature(orig_input)) { - return false; - } - - // Derive node.public_key and fill script_sig with the legacy scriptPubKey - // (aka BIP-143 script code), which is what our code expects here in order - // to properly compute the legacy transaction digest or BIP-143 transaction - // digest. - if (!derive_node(orig_input) || !fill_input_script_sig(orig_input)) { - return false; + // Remember the first original internal legacy input. + if ((orig_input->script_type == InputScriptType_SPENDMULTISIG || + orig_input->script_type == InputScriptType_SPENDADDRESS) && + !coin->force_bip143 && !coin->overwintered) { + if (orig_info.next_legacy_input == 0xffffffff) { + orig_info.next_legacy_input = idx2; } - - // Save the verification input with script_sig set to scriptPubKey. - memcpy(&orig_verif_input, orig_input, sizeof(TxInputType)); - orig_verif_input_idx = idx2; - have_orig_verif_input = true; - } else { - orig_input->script_sig.size = 0; - } - - // Add input to original legacy digest computation now that script_sig is set. - if (!tx_serialize_input_hash(&ti, orig_input)) { - fsm_sendFailure(FailureType_Failure_ProcessError, - _("Failed to serialize input")); - signing_abort(); - return false; } return true; @@ -1748,10 +1823,8 @@ static bool signing_add_orig_output(TxOutputType *orig_output) { return false; } - // Add output to the original legacy digest computation (ti) and to the - // original TXID computation (tp). - if (!tx_serialize_output_hash(&ti, &orig_bin_output) || - !tx_serialize_output_hash(&tp, &orig_bin_output)) { + // Add output to original TXID computation. + if (!tx_serialize_output_hash(&tp, &orig_bin_output)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize output")); signing_abort(); @@ -2158,39 +2231,30 @@ static void signing_hash_zip244(const TxInfo *tx_info, } #endif -static bool signing_check_orig_tx(void) { - uint8_t hash[32] = {0}; +static bool signing_verify_orig_nonlegacy_input(TxInputType *orig_input) { + // Nothing to verify for external inputs. + if (orig_input->script_type == InputScriptType_EXTERNAL) { + return true; + } - // Finalize original TXID computation and ensure it matches orig_hash. - tx_hash_final(&tp, hash, true); - if (memcmp(hash, orig_hash, sizeof(orig_hash)) != 0) { - // This may happen if incorrect information is supplied in the TXORIGINPUT - // or TXORIGOUTPUT responses or if the device is loaded with the wrong seed, - // because we derive the scriptPubKeys of change-outputs from the seed using - // the provided path. - fsm_sendFailure(FailureType_Failure_ProcessError, - _("Invalid original TXID.")); - signing_abort(); + // Save the signature before script_sig is overwritten. + if (!save_signature(orig_input)) { return false; } - if (!have_orig_verif_input) { - fsm_sendFailure(FailureType_Failure_ProcessError, - _("The original transaction must specify address_n for at " - "least one input.")); - signing_abort(); + // Derive node.public_key and fill script_sig with the legacy scriptPubKey + // (aka BIP-143 script code), which is what our code expects here in order + // to properly compute the BIP-143 transaction digest. + if (!derive_node(orig_input) || !fill_input_script_sig(orig_input)) { return false; } - // Finish computation of BIP-143/BIP-341/ZIP-243 sub-hashes. - tx_info_finish(&orig_info); - // Compute the signed digest and verify signature. - uint32_t hash_type = signing_hash_type(&orig_verif_input); + uint8_t hash[32] = {0}; + uint32_t hash_type = signing_hash_type(orig_input); bool valid = false; - if (orig_verif_input.script_type == InputScriptType_SPENDTAPROOT) { - signing_hash_bip341(&orig_info, orig_verif_input_idx, hash_type & 0xff, - hash); + if (orig_input->script_type == InputScriptType_SPENDTAPROOT) { + signing_hash_bip341(&orig_info, idx1, hash_type & 0xff, hash); uint8_t output_public_key[32] = {0}; valid = (zkp_bip340_tweak_public_key(node.public_key + 1, NULL, output_public_key) == 0) && @@ -2198,18 +2262,11 @@ static bool signing_check_orig_tx(void) { } else { #if !BITCOIN_ONLY if (coin->overwintered) { - signing_hash_zip243(&orig_info, &orig_verif_input, hash); + signing_hash_zip243(&orig_info, orig_input, hash); } else #endif { - if (is_segwit_input_script_type(&orig_verif_input) || - coin->force_bip143) { - signing_hash_bip143(&orig_info, &orig_verif_input, hash); - } else { - // Finalize legacy digest computation. - hasher_Update(&ti.hasher, (const uint8_t *)&hash_type, 4); - tx_hash_final(&ti, hash, false); - } + signing_hash_bip143(&orig_info, orig_input, hash); } #ifdef USE_SECP256K1_ZKP_ECDSA @@ -2232,6 +2289,142 @@ static bool signing_check_orig_tx(void) { return valid; } +static bool signing_verify_orig_legacy_input(void) { + // Finalize legacy digest computation. + uint32_t hash_type = signing_hash_type(&input); + hasher_Update(&ti.hasher, (const uint8_t *)&hash_type, 4); + + // Compute the signed digest and verify signature. + uint8_t hash[32] = {0}; + tx_hash_final(&ti, hash, false); + + bool valid = false; +#ifdef USE_SECP256K1_ZKP_ECDSA + if (coin->curve->params == &secp256k1) { + valid = zkp_ecdsa_verify_digest(coin->curve->params, node.public_key, sig, + hash) == 0; + } else +#endif + { + valid = ecdsa_verify_digest(coin->curve->params, node.public_key, sig, + hash) == 0; + } + + if (!valid) { + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid signature.")); + signing_abort(); + } + + return valid; +} + +static bool signing_hash_orig_input(TxInputType *orig_input) { + if (idx2 == 0) { + uint32_t branch_id = 0; +#if !BITCOIN_ONLY + branch_id = orig_info.branch_id; +#endif + tx_init(&ti, orig_info.inputs_count, orig_info.outputs_count, + orig_info.version, orig_info.lock_time, orig_info.expiry, branch_id, + 0, coin->curve->hasher_sign, coin->overwintered, + orig_info.version_group_id, orig_info.timestamp); + // Reset the inner transaction check. + hasher_Reset(&orig_info.hasher_check); + } + + // Add input to the inner transaction check. + if (!tx_input_check_hash(&orig_info.hasher_check, orig_input)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to hash input")); + signing_abort(); + return false; + } + + if (idx2 == idx1) { + // Add input to the outer transaction check. + if (!tx_input_check_hash(&hasher_check, orig_input)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to hash input")); + signing_abort(); + return false; + } + + // Save the signature before script_sig is overwritten. + if (!save_signature(orig_input)) { + return false; + } + + // Derive node.public_key and fill script_sig with the legacy + // scriptPubKey which is what our code expects here in order to properly + // compute the transaction digest. + if (!derive_node(orig_input) || !fill_input_script_sig(orig_input)) { + return false; + } + + memcpy(&input, orig_input, sizeof(input)); + } else { + if (orig_info.next_legacy_input == idx1 && idx2 > idx1 && + (orig_input->script_type == InputScriptType_SPENDADDRESS || + orig_input->script_type == InputScriptType_SPENDMULTISIG)) { + orig_info.next_legacy_input = idx2; + } + orig_input->script_sig.size = 0; + } + + // Add input to original legacy digest computation now that script_sig is + // set. + if (!tx_serialize_input_hash(&ti, orig_input)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to serialize input")); + signing_abort(); + return false; + } + + return true; +} + +static bool signing_hash_orig_output(TxOutputType *orig_output) { + if (compile_output(coin, amount_unit, &root, orig_output, &bin_output, + false) <= 0) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to compile output")); + signing_abort(); + return false; + } + + // Add the output to the inner transaction check. + tx_output_hash(&orig_info.hasher_check, &bin_output, coin->decred); + + // Add the output to original legacy digest computation + if (!tx_serialize_output_hash(&ti, &bin_output)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to serialize output")); + signing_abort(); + return false; + } + + return true; +} + +static bool signing_check_orig_tx(void) { + uint8_t hash[32] = {0}; + + // Finalize original TXID computation and ensure it matches orig_hash. + tx_hash_final(&tp, hash, true); + if (memcmp(hash, orig_hash, sizeof(orig_hash)) != 0) { + // This may happen if incorrect information is supplied in the TXORIGINPUT + // or TXORIGOUTPUT responses or if the device is loaded with the wrong seed, + // because we derive the scriptPubKeys of change-outputs from the seed using + // the provided path. + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Invalid original TXID.")); + signing_abort(); + return false; + } + + return true; +} + static void phase1_finish(void) { #if !BITCOIN_ONLY if (coin->decred) { @@ -2240,8 +2433,9 @@ static void phase1_finish(void) { } #endif - // Compute BIP143 hashPrevouts, hashSequence and hashOutputs. + // Finish computation of BIP-143/BIP-341/ZIP-243 sub-hashes. tx_info_finish(&info); + tx_info_finish(&orig_info); if (is_replacement) { if (!signing_check_orig_tx()) { @@ -2254,11 +2448,17 @@ static void phase1_finish(void) { } if (taproot_only) { - // All internal inputs are Taproot. We do not need to verify them so we - // proceed directly to Phase 2, where the transaction will be signed. We can - // trust the amounts and scriptPubKeys, because if an invalid value is - // provided then all issued signatures will be invalid. - phase2_request_next_input(); + // All internal inputs are Taproot. We do not need to verify that their + // parameters match previous transactions. We can trust the amounts and + // scriptPubKeys, because if an invalid value is provided then all issued + // signatures will be invalid. + if (is_replacement) { + // Verify original transaction. + phase2_request_orig_input(); + } else { + // Proceed directly to transaction signing. + phase2_request_next_input(); + } #if !BITCOIN_ONLY } else if (coin->overwintered && info.version == 5) { // ZIP-244 transactions are treated same as Taproot. @@ -2711,11 +2911,6 @@ void signing_txack(TransactionType *tx) { return; } - // Initialize computation of original legacy digest. - tx_init(&ti, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, - tx->expiry, tx->branch_id, 0, coin->curve->hasher_sign, - coin->overwintered, tx->version_group_id, tx->timestamp); - // Initialize computation of original TXID. tx_init(&tp, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, tx->expiry, tx->branch_id, tx->extra_data_len, @@ -3000,6 +3195,79 @@ void signing_txack(TransactionType *tx) { } return; #endif + + case STAGE_REQUEST_3_ORIG_NONLEGACY_INPUT: + if (!signing_validate_input(tx->inputs)) { + return; + } + + // Add input to the outer transaction check. + if (!tx_input_check_hash(&hasher_check, tx->inputs)) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Failed to hash input")); + signing_abort(); + return; + } + + if (!signing_verify_orig_nonlegacy_input(tx->inputs)) { + return; + } + + idx1++; + phase2_request_orig_input(); + return; + + case STAGE_REQUEST_3_ORIG_INPUT: + if (!signing_validate_input(tx->inputs) || + !signing_hash_orig_input(tx->inputs)) { + return; + } + + idx2++; + if (idx2 < orig_info.inputs_count) { + send_req_3_orig_input(); + } else { + // Ensure that the original transaction inputs haven't changed for the + // inner transaction check. + if (!tx_info_check_inputs_hash(&orig_info)) { + return; + } + + // Reset the inner transaction check. + hasher_Reset(&orig_info.hasher_check); + idx2 = 0; + send_req_3_orig_output(); + } + + return; + + case STAGE_REQUEST_3_ORIG_OUTPUT: + if (!signing_validate_output(tx->outputs) || + !signing_hash_orig_output(tx->outputs)) { + return; + } + + idx2++; + if (idx2 < orig_info.outputs_count) { + send_req_3_orig_output(); + } else { + // Ensure that the original transaction outputs haven't changed for the + // inner transaction check. + if (!tx_info_check_outputs_hash(&orig_info)) { + return; + } + + // Verify original signature. + if (!signing_verify_orig_legacy_input()) { + return; + } + + idx1++; + phase2_request_orig_input(); + } + + return; + case STAGE_REQUEST_4_INPUT: if (!signing_validate_input(&tx->inputs[0])) { return; diff --git a/tests/device_tests/bitcoin/test_signtx_replacement.py b/tests/device_tests/bitcoin/test_signtx_replacement.py index ea31895a3..5b230e5cd 100644 --- a/tests/device_tests/bitcoin/test_signtx_replacement.py +++ b/tests/device_tests/bitcoin/test_signtx_replacement.py @@ -133,10 +133,10 @@ def test_p2pkh_fee_bump(client: Client): request_meta(TXHASH_beafc7), request_input(0, TXHASH_beafc7), request_output(0, TXHASH_beafc7), - request_orig_input(0, TXHASH_50f6f1), (tt, request_orig_input(0, TXHASH_50f6f1)), - (tt, request_orig_output(0, TXHASH_50f6f1)), - (tt, request_orig_output(1, TXHASH_50f6f1)), + request_orig_input(0, TXHASH_50f6f1), + request_orig_output(0, TXHASH_50f6f1), + request_orig_output(1, TXHASH_50f6f1), request_input(0), request_output(0), request_output(1), diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index a8c3b2a98..95799cbc0 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -276,11 +276,11 @@ "T1_bitcoin-test_signtx_replacement.py::test_attack_steal_change": "3a79850fe95abbd2ca342fc62ba7f6404c4f437977764839a8146789ac811fce", "T1_bitcoin-test_signtx_replacement.py::test_p2pkh_fee_bump": "a386c4c61f5fe3b073db6b8725193f5bf7881d7b6fae175ff7d879f7c94eb795", "T1_bitcoin-test_signtx_replacement.py::test_p2tr_fee_bump": "00f4f745f88f1072f495e513d6a7747db494bb7c785c32d167652fe1d79509be", -"T1_bitcoin-test_signtx_replacement.py::test_p2tr_invalid_signature": "1f46b6ec89be1742dc4649153e6d13b172c9e93be7c91063650f814e631b757c", +"T1_bitcoin-test_signtx_replacement.py::test_p2tr_invalid_signature": "00f4f745f88f1072f495e513d6a7747db494bb7c785c32d167652fe1d79509be", "T1_bitcoin-test_signtx_replacement.py::test_p2wpkh_finalize": "7b3b6ebee78fed0e64c9689c64c5fbf73099812c5452b2fd2dbe2c23cd69b669", "T1_bitcoin-test_signtx_replacement.py::test_p2wpkh_in_p2sh_fee_bump_from_external": "3d7d6ad6eafe3399f9d3aa5bb358e4c04f83a98b68ccfa8a124b7e63c0f6df78", "T1_bitcoin-test_signtx_replacement.py::test_p2wpkh_in_p2sh_remove_change": "14544554428651eb22515a88418c71f66de68e581ea2df5b2259843b1931e8fc", -"T1_bitcoin-test_signtx_replacement.py::test_p2wpkh_invalid_signature": "ee190f0d9f972f005c706a818872a18778aa570737b65e5bebbe6edbe6396008", +"T1_bitcoin-test_signtx_replacement.py::test_p2wpkh_invalid_signature": "7b3b6ebee78fed0e64c9689c64c5fbf73099812c5452b2fd2dbe2c23cd69b669", "T1_bitcoin-test_signtx_replacement.py::test_p2wpkh_op_return_fee_bump": "897291942225c61f9b641c7a1287960e7c21d80ada6c75414399d76edc41054c", "T1_bitcoin-test_signtx_segwit.py::test_attack_change_input_address": "fb82fd6c801028181ea89cc517c1401ca78d319b1b9d60e19e5b1cc0107a083f", "T1_bitcoin-test_signtx_segwit.py::test_attack_mixed_inputs": "614206bc232bf0a07846361bd21a2a0520c8384f052ba362d227e17c33013270", From 78feb5fe0314a2358ac82a00430954b7ceb9be2f Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Tue, 29 Mar 2022 16:17:49 +0200 Subject: [PATCH 24/32] chore(common): update coin support status --- common/defs/coins_details.json | 10 +++++----- common/defs/coins_details.override.json | 3 +++ common/defs/misc/misc.json | 3 ++- common/defs/wallets.json | 3 +-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/common/defs/coins_details.json b/common/defs/coins_details.json index 52e24f066..2b179ec92 100644 --- a/common/defs/coins_details.json +++ b/common/defs/coins_details.json @@ -563,10 +563,6 @@ { "name": "Electrum-RVN", "url": "https://github.com/traysi/electrum-raven" - }, - { - "name": "Mango Farm", - "url": "https://mangofarmassets.com/mangowallet" } ] }, @@ -20464,7 +20460,7 @@ "marketcap_usd": 0, "name": "Sola Token", "network": "eth", - "shortcut": "SOL", + "shortcut": "SOLA", "t1_enabled": "yes", "t2_enabled": "yes", "type": "erc20", @@ -36095,6 +36091,10 @@ { "name": "Exodus", "url": "https://www.exodus.io" + }, + { + "name": "Stellarport", + "url": "https://stellarport.io/" } ] }, diff --git a/common/defs/coins_details.override.json b/common/defs/coins_details.override.json index 71002f622..26675039f 100644 --- a/common/defs/coins_details.override.json +++ b/common/defs/coins_details.override.json @@ -5,6 +5,9 @@ "erc20:eth:LINK (Chainlink)": { "name": "Chainlink" }, + "erc20:eth:SOL": { + "shortcut": "SOLA" + }, "eth:CLO": { "coinmarketcap_alias": "callisto-network" }, diff --git a/common/defs/misc/misc.json b/common/defs/misc/misc.json index 72a011f8b..719053526 100644 --- a/common/defs/misc/misc.json +++ b/common/defs/misc/misc.json @@ -25,7 +25,8 @@ }, "wallet": { "Account Viewer": "https://accountviewer.stellar.org/", - "Exodus": "https://www.exodus.io" + "Exodus": "https://www.exodus.io", + "Stellarport": "https://stellarport.io/" } }, { diff --git a/common/defs/wallets.json b/common/defs/wallets.json index 5c450b439..09f4b297b 100644 --- a/common/defs/wallets.json +++ b/common/defs/wallets.json @@ -82,8 +82,7 @@ }, "bitcoin:RVN": { "Chaintek": "https://wallet.chaintek.net/", - "Electrum-RVN": "https://github.com/traysi/electrum-raven", - "Mango Farm": "https://mangofarmassets.com/mangowallet" + "Electrum-RVN": "https://github.com/traysi/electrum-raven" }, "bitcoin:SMART": { "Electrum-SMART": "https://github.com/smartcash/electrum-smart" From 29bab9e8a459d23b258daf23382440eb1e3d3324 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Tue, 29 Mar 2022 17:54:06 +0200 Subject: [PATCH 25/32] chore(common): update chains and tokens --- common/defs/coins_details.json | 2558 +++++++++++++++++++--------- common/defs/ethereum/chains | 2 +- common/defs/ethereum/tokens | 2 +- common/defs/support.json | 348 +++- common/tools/coin_info.py | 3 +- core/src/apps/ethereum/networks.py | 283 ++- core/src/apps/ethereum/tokens.py | 102 +- 7 files changed, 2295 insertions(+), 1003 deletions(-) diff --git a/common/defs/coins_details.json b/common/defs/coins_details.json index 2b179ec92..eea18f331 100644 --- a/common/defs/coins_details.json +++ b/common/defs/coins_details.json @@ -5,7 +5,7 @@ "Github": "https://github.com/Actinium-project/Actinium", "Homepage": "https://actinium.org" }, - "marketcap_usd": 538232, + "marketcap_usd": 643850, "name": "Actinium", "shortcut": "ACM", "t1_enabled": "yes", @@ -23,7 +23,7 @@ "Github": "https://github.com/axerunners/axe", "Homepage": "https://axerunners.com" }, - "marketcap_usd": 140889, + "marketcap_usd": 87492, "name": "Axe", "shortcut": "AXE", "t1_enabled": "yes", @@ -41,7 +41,7 @@ "Github": "https://github.com/Bitcoin-ABC/bitcoin-abc", "Homepage": "https://www.bitcoincash.org" }, - "marketcap_usd": 8511687615, + "marketcap_usd": 7219413148, "name": "Bitcoin Cash", "shortcut": "BCH", "t1_enabled": "yes", @@ -67,7 +67,7 @@ "Github": "https://github.com/bitcoin/bitcoin", "Homepage": "https://bitcoin.org" }, - "marketcap_usd": 942450091241, + "marketcap_usd": 909440053192, "name": "Bitcoin", "shortcut": "BTC", "t1_enabled": "yes", @@ -93,7 +93,7 @@ "Github": "https://github.com/BTCPrivate/BitcoinPrivate", "Homepage": "https://btcprivate.org" }, - "marketcap_usd": 9532520, + "marketcap_usd": 17476086, "name": "Bitcoin Private", "shortcut": "BTCP", "t1_enabled": "yes", @@ -111,7 +111,7 @@ "Github": "https://github.com/BTCGPU/BTCGPU", "Homepage": "https://bitcoingold.org" }, - "marketcap_usd": 777128642, + "marketcap_usd": 783476449, "name": "Bitcoin Gold", "shortcut": "BTG", "t1_enabled": "yes", @@ -137,7 +137,7 @@ "Github": "https://github.com/LIMXTEC/BitCore", "Homepage": "https://bitcore.cc" }, - "marketcap_usd": 3622325, + "marketcap_usd": 1556795, "name": "Bitcore", "shortcut": "BTX", "t1_enabled": "yes", @@ -155,7 +155,7 @@ "Github": "https://github.com/cpuchain/cpuchain", "Homepage": "https://cpuchain.org" }, - "marketcap_usd": 37973, + "marketcap_usd": 107731, "name": "CPUchain", "shortcut": "CPU", "t1_enabled": "yes", @@ -173,20 +173,25 @@ "Github": "https://github.com/Crowndev/crowncoin", "Homepage": "https://crownplatform.com" }, - "marketcap_usd": 1518176, + "marketcap_usd": 1138620, "name": "Crown", "shortcut": "CRW", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", - "wallet": [] + "wallet": [ + { + "name": "Crown-Electrum", + "url": "https://github.com/Crowndev/crown-electrum" + } + ] }, "bitcoin:DASH": { "links": { "Github": "https://github.com/dashpay/dash", "Homepage": "https://www.dash.org" }, - "marketcap_usd": 1568226287, + "marketcap_usd": 1405875317, "name": "Dash", "shortcut": "DASH", "t1_enabled": "yes", @@ -216,7 +221,7 @@ "Github": "https://github.com/decred/dcrd", "Homepage": "https://www.decred.org" }, - "marketcap_usd": 1084169176, + "marketcap_usd": 926018012, "name": "Decred", "shortcut": "DCR", "t1_enabled": "yes", @@ -234,7 +239,7 @@ "Github": "https://github.com/digibyte/digibyte", "Homepage": "https://digibyte.io" }, - "marketcap_usd": 556184350, + "marketcap_usd": 523256573, "name": "DigiByte", "shortcut": "DGB", "t1_enabled": "yes", @@ -256,7 +261,7 @@ "Github": "https://github.com/dogecoin/dogecoin", "Homepage": "https://dogecoin.com" }, - "marketcap_usd": 24978887703, + "marketcap_usd": 19473522353, "name": "Dogecoin", "shortcut": "DOGE", "t1_enabled": "yes", @@ -291,7 +296,7 @@ "Github": "https://github.com/firoorg/firo", "Homepage": "https://firo.org" }, - "marketcap_usd": 72167401, + "marketcap_usd": 58990223, "name": "Firo", "shortcut": "FIRO", "t1_enabled": "yes", @@ -313,7 +318,7 @@ "Github": "https://github.com/fujicoin/fujicoin", "Homepage": "https://fujicoin.org" }, - "marketcap_usd": 1946652, + "marketcap_usd": 1958813, "name": "Fujicoin", "shortcut": "FJC", "t1_enabled": "yes", @@ -349,7 +354,7 @@ "Github": "https://github.com/FeatherCoin/Feathercoin", "Homepage": "https://feathercoin.com" }, - "marketcap_usd": 3184945, + "marketcap_usd": 1812248, "name": "Feathercoin", "shortcut": "FTC", "t1_enabled": "yes", @@ -367,7 +372,7 @@ "Github": "https://github.com/Groestlcoin/groestlcoin", "Homepage": "https://www.groestlcoin.org" }, - "marketcap_usd": 61352230, + "marketcap_usd": 59823174, "name": "Groestlcoin", "shortcut": "GRS", "t1_enabled": "yes", @@ -385,7 +390,7 @@ "Github": "https://github.com/komodoplatform/komodo", "Homepage": "https://komodoplatform.com" }, - "marketcap_usd": 102659995, + "marketcap_usd": 76380332, "name": "Komodo", "shortcut": "KMD", "t1_enabled": "yes", @@ -416,7 +421,7 @@ "Github": "https://github.com/litecoin-project/litecoin", "Homepage": "https://litecoin.org" }, - "marketcap_usd": 10718044538, + "marketcap_usd": 9102568402, "name": "Litecoin", "shortcut": "LTC", "t1_enabled": "yes", @@ -442,7 +447,7 @@ "Github": "https://github.com/monacoinproject/monacoin", "Homepage": "https://monacoin.org" }, - "marketcap_usd": 88119215, + "marketcap_usd": 65906519, "name": "Monacoin", "shortcut": "MONA", "t1_enabled": "yes", @@ -460,7 +465,7 @@ "Github": "https://github.com/muecoin/MUE", "Homepage": "https://www.monetaryunit.org" }, - "marketcap_usd": 1085506, + "marketcap_usd": 830517, "name": "MonetaryUnit", "shortcut": "MUE", "t1_enabled": "yes", @@ -478,7 +483,7 @@ "Github": "https://github.com/namecoin/namecoin-core", "Homepage": "https://namecoin.org" }, - "marketcap_usd": 22728332, + "marketcap_usd": 35773607, "name": "Namecoin", "shortcut": "NMC", "t1_enabled": "yes", @@ -500,7 +505,7 @@ "Github": "https://github.com/peercoin/peercoin", "Homepage": "https://peercoin.net" }, - "marketcap_usd": 20502681, + "marketcap_usd": 16244915, "name": "Peercoin", "shortcut": "PPC", "t1_enabled": "yes", @@ -513,7 +518,7 @@ "Github": "https://github.com/qtumproject/qtum", "Homepage": "https://qtum.org" }, - "marketcap_usd": 966841886, + "marketcap_usd": 854953214, "name": "Qtum", "shortcut": "QTUM", "t1_enabled": "yes", @@ -531,7 +536,7 @@ "Github": "https://github.com/RitoProject", "Homepage": "https://ritocoin.org" }, - "marketcap_usd": 313889, + "marketcap_usd": 160421, "name": "Ritocoin", "shortcut": "RITO", "t1_enabled": "yes", @@ -549,7 +554,7 @@ "Github": "https://github.com/RavenProject/Ravencoin", "Homepage": "https://ravencoin.org" }, - "marketcap_usd": 991377797, + "marketcap_usd": 750559910, "name": "Ravencoin", "shortcut": "RVN", "t1_enabled": "yes", @@ -571,7 +576,7 @@ "Github": "https://github.com/SmartCash/Core-Smart", "Homepage": "https://smartcash.cc" }, - "marketcap_usd": 4251230, + "marketcap_usd": 2318067, "name": "SmartCash", "shortcut": "SMART", "t1_enabled": "yes", @@ -589,7 +594,7 @@ "Github": "https://github.com/syscoin/syscoin", "Homepage": "https://syscoin.org" }, - "marketcap_usd": 507953217, + "marketcap_usd": 440397266, "name": "Syscoin", "shortcut": "SYS", "t1_enabled": "yes", @@ -625,7 +630,7 @@ "Github": "https://github.com/viacoin", "Homepage": "https://viacoin.org" }, - "marketcap_usd": 4159657, + "marketcap_usd": 2895597, "name": "Viacoin", "shortcut": "VIA", "t1_enabled": "yes", @@ -661,7 +666,7 @@ "Github": "https://github.com/vertcoin-project/vertcoin-core", "Homepage": "https://vertcoin.org" }, - "marketcap_usd": 30881897, + "marketcap_usd": 20109915, "name": "Vertcoin", "shortcut": "VTC", "t1_enabled": "yes", @@ -679,7 +684,7 @@ "Github": "https://github.com/primecoin/primecoin", "Homepage": "https://primecoin.io" }, - "marketcap_usd": 4200551, + "marketcap_usd": 2806223, "name": "Primecoin", "shortcut": "XPM", "t1_enabled": "yes", @@ -697,7 +702,7 @@ "Github": "https://gitlab.com/bitcoinrh/BRhodiumNode", "Homepage": "https://xrhodium.org" }, - "marketcap_usd": 5607172, + "marketcap_usd": 968087, "name": "xRhodium", "shortcut": "XRC", "t1_enabled": "yes", @@ -715,7 +720,7 @@ "Github": "https://github.com/X9Developers/XSN", "Homepage": "https://stakenet.io" }, - "marketcap_usd": 14364033, + "marketcap_usd": 2989674, "name": "Stakenet", "shortcut": "XSN", "t1_enabled": "yes", @@ -733,7 +738,7 @@ "Github": "https://github.com/vergecurrency/VERGE", "Homepage": "https://vergecurrency.com" }, - "marketcap_usd": 316115226, + "marketcap_usd": 207359599, "name": "Verge", "shortcut": "XVG", "t1_enabled": "yes", @@ -751,7 +756,7 @@ "Github": "https://github.com/zcore-coin/zcore-2.0", "Homepage": "https://zcore.cash" }, - "marketcap_usd": 145521, + "marketcap_usd": 70634, "name": "ZCore", "shortcut": "ZCR", "t1_enabled": "yes", @@ -769,7 +774,7 @@ "Github": "https://github.com/zcash/zcash", "Homepage": "https://z.cash" }, - "marketcap_usd": 2219134481, + "marketcap_usd": 2757663403, "name": "Zcash", "shortcut": "ZEC", "t1_enabled": "yes", @@ -910,7 +915,7 @@ "links": { "Homepage": "https://0xbitcoin.org/" }, - "marketcap_usd": 9316054, + "marketcap_usd": 6245135, "name": "0xBitcoin", "network": "eth", "shortcut": "0xBTC", @@ -968,7 +973,7 @@ "links": { "Homepage": "https://ico.1worldonline.com" }, - "marketcap_usd": 3544404, + "marketcap_usd": 3973354, "name": "1World", "network": "eth", "shortcut": "1WO", @@ -1046,7 +1051,7 @@ "Github": "https://github.com/crypt04dvisor/AlphaWallet", "Homepage": "https://alphaplatform.co/" }, - "marketcap_usd": 233735, + "marketcap_usd": 534951, "name": "Alpha", "network": "eth", "shortcut": "A", @@ -1066,7 +1071,7 @@ "Github": "https://github.com/aave", "Homepage": "https://aave.com/ " }, - "marketcap_usd": 3481392580, + "marketcap_usd": 2827679640, "name": "Aave", "network": "eth", "shortcut": "AAVE", @@ -1145,7 +1150,7 @@ "links": { "Homepage": "https://www.arcblock.io" }, - "marketcap_usd": 16084177, + "marketcap_usd": 13904197, "name": "ArcBlock Token", "network": "eth", "shortcut": "ABT", @@ -1165,7 +1170,7 @@ "Github": "https://github.com/theabyssportal", "Homepage": "https://www.theabyss.com" }, - "marketcap_usd": 7048431, + "marketcap_usd": 9236667, "name": "Abyss Token", "network": "eth", "shortcut": "ABYSS", @@ -1222,7 +1227,7 @@ "links": { "Homepage": "https://adbank.network" }, - "marketcap_usd": 1937404, + "marketcap_usd": 965952, "name": "adbank", "network": "eth", "shortcut": "ADB", @@ -1301,7 +1306,7 @@ "Github": "https://github.com/aditus", "Homepage": "https://aditus.net" }, - "marketcap_usd": 65417, + "marketcap_usd": 99092, "name": "Aditus", "network": "eth", "shortcut": "ADI", @@ -1380,7 +1385,7 @@ "Github": "https://github.com/AdExNetwork", "Homepage": "https://www.adex.network" }, - "marketcap_usd": 84432800, + "marketcap_usd": 63154215, "name": "AdEx Network", "network": "eth", "shortcut": "ADX", @@ -1514,6 +1519,26 @@ } ] }, + "erc20:eth:AGRS": { + "address": "0x738865301A9b7Dd80Dc3666dD48cF034ec42bdDa", + "links": { + "Github": "https://github.com/IDNI", + "Homepage": "https://tau.net/" + }, + "marketcap_usd": 11129222, + "name": "Agoras: Currency of Tau", + "network": "eth", + "shortcut": "AGRS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:AGS": { "address": "0x7db5454F3500f28171d1f9c7a38527C9cF94e6b2", "links": { @@ -1558,7 +1583,7 @@ "links": { "Homepage": "https://www.aidcoin.co" }, - "marketcap_usd": 602319, + "marketcap_usd": 305138, "name": "AidCoin", "network": "eth", "shortcut": "AID", @@ -1617,7 +1642,7 @@ "Github": "https://github.com/AigangNetwork", "Homepage": "https://aigang.network/" }, - "marketcap_usd": 668483, + "marketcap_usd": 374146, "name": "Aigang", "network": "eth", "shortcut": "AIX", @@ -1676,7 +1701,7 @@ "Github": "https://github.com/aleph-im/", "Homepage": "https://aleph.im" }, - "marketcap_usd": 87287235, + "marketcap_usd": 62417626, "name": "Aleph.im", "network": "eth", "shortcut": "ALEPH", @@ -1695,7 +1720,7 @@ "links": { "Homepage": "http://ailink.in" }, - "marketcap_usd": 297495, + "marketcap_usd": 182328, "name": "AiLink Token", "network": "eth", "shortcut": "ALI", @@ -1729,6 +1754,26 @@ } ] }, + "erc20:eth:ALTA": { + "address": "0xe0cCa86B254005889aC3a81e737f56a14f4A38F5", + "links": { + "Github": "https://github.com/altafinprotocol", + "Homepage": "https://alta.finance" + }, + "marketcap_usd": 0, + "name": "Alta Finance", + "network": "eth", + "shortcut": "ALTA", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:ALTS": { "address": "0x638AC149eA8EF9a1286C41B977017AA7359E6Cfa", "links": { @@ -1833,7 +1878,7 @@ "Github": "https://github.com/amlt-by-coinfirm", "Homepage": "https://amlt.coinfirm.io/" }, - "marketcap_usd": 8661687, + "marketcap_usd": 3704621, "name": "AMLT", "network": "eth", "shortcut": "AMLT", @@ -1853,7 +1898,7 @@ "Github": "https://github.com/amontech", "Homepage": "https://amon.tech" }, - "marketcap_usd": 1703196, + "marketcap_usd": 1388057, "name": "Amon", "network": "eth", "shortcut": "AMN", @@ -1873,7 +1918,7 @@ "Github": "https://github.com/AMO-Project/", "Homepage": "https://amo.foundation" }, - "marketcap_usd": 51447157, + "marketcap_usd": 35001668, "name": "AMO Coin", "network": "eth", "shortcut": "AMO", @@ -1892,7 +1937,7 @@ "links": { "Homepage": "https://ados.foundation/" }, - "marketcap_usd": 920486, + "marketcap_usd": 1342255, "name": "Token AmonD", "network": "eth", "shortcut": "AMON", @@ -1912,7 +1957,7 @@ "Github": "https://github.com/amptoken", "Homepage": "https://amptoken.org" }, - "marketcap_usd": 2130246978, + "marketcap_usd": 1168152518, "name": "Amp", "network": "eth", "shortcut": "AMP", @@ -1932,7 +1977,7 @@ "Github": "https://github.com/ampleforth", "Homepage": "https://ampleforth.org" }, - "marketcap_usd": 183626476, + "marketcap_usd": 87761062, "name": "Ampleforth", "network": "eth", "shortcut": "AMPL", @@ -1991,7 +2036,7 @@ "Github": "https://github.com/aragon/aragon-court", "Homepage": "https://anj.aragon.org/" }, - "marketcap_usd": 36841951, + "marketcap_usd": 34304320, "name": "Aragon Network Juror", "network": "eth", "shortcut": "ANJ", @@ -2010,7 +2055,7 @@ "links": { "Homepage": "https://www.aurorachain.io" }, - "marketcap_usd": 16672966, + "marketcap_usd": 9216375, "name": "Aurora", "network": "eth", "shortcut": "AOA", @@ -2030,7 +2075,7 @@ "Github": "https://github.com/api3dao", "Homepage": "https://api3.org/" }, - "marketcap_usd": 174927973, + "marketcap_usd": 215836440, "name": "API3", "network": "eth", "shortcut": "API3", @@ -2109,7 +2154,7 @@ "Github": "https://github.com/alphaquark/Alpha-Quark", "Homepage": "https://www.alphaquark.io" }, - "marketcap_usd": 105579694, + "marketcap_usd": 81858314, "name": "AlphaQuarkToken", "network": "eth", "shortcut": "AQT", @@ -2148,7 +2193,7 @@ "links": { "Homepage": "https://www.arbitragect.com" }, - "marketcap_usd": 52179, + "marketcap_usd": 100201, "name": "ArbitrageCT", "network": "eth", "shortcut": "ARCT", @@ -2227,7 +2272,7 @@ "Github": "https://github.com/aeronaero/aeron", "Homepage": "https://aeron.aero" }, - "marketcap_usd": 9971, + "marketcap_usd": 9574, "name": "Aeron", "network": "eth", "shortcut": "ARNX", @@ -2246,7 +2291,7 @@ "links": { "Homepage": "http://www.maecenas.co" }, - "marketcap_usd": 229205, + "marketcap_usd": 140171, "name": "Maecenas", "network": "eth", "shortcut": "ART", @@ -2324,7 +2369,7 @@ "links": { "Homepage": "https://airswap.io" }, - "marketcap_usd": 44120974, + "marketcap_usd": 26934363, "name": "Airswap", "network": "eth", "shortcut": "AST", @@ -2363,7 +2408,7 @@ "links": { "Homepage": "https://atlant.io" }, - "marketcap_usd": 1658951, + "marketcap_usd": 659342, "name": "ATLANT", "network": "eth", "shortcut": "ATL", @@ -2479,7 +2524,7 @@ "links": { "Homepage": "https://auctus.org" }, - "marketcap_usd": 2526592, + "marketcap_usd": 1397475, "name": "Auctus", "network": "eth", "shortcut": "AUC", @@ -2499,7 +2544,7 @@ "Github": "https://github.com/audiusproject", "Homepage": "https://audius.co" }, - "marketcap_usd": 983286940, + "marketcap_usd": 689264363, "name": "Audius", "network": "eth", "shortcut": "AUDIO", @@ -2596,7 +2641,7 @@ "links": { "Homepage": "https://aventus.io" }, - "marketcap_usd": 16090525, + "marketcap_usd": 17270857, "name": "Aventus", "network": "eth", "shortcut": "AVT", @@ -2695,7 +2740,7 @@ "Github": "https://github.com/axieinfinity", "Homepage": "https://axieinfinity.com/" }, - "marketcap_usd": 6515764008, + "marketcap_usd": 4263086025, "name": "Axie Infinity Shards", "network": "eth", "shortcut": "AXS", @@ -2754,7 +2799,7 @@ "Github": "https://github.com/balancer-labs", "Homepage": "https://balancer.finance" }, - "marketcap_usd": 124195101, + "marketcap_usd": 104549974, "name": "Balancer", "network": "eth", "shortcut": "BAL", @@ -2813,7 +2858,7 @@ "links": { "Homepage": "https://www.banca.world" }, - "marketcap_usd": 623057, + "marketcap_usd": 581046, "name": "Banca", "network": "eth", "shortcut": "BANCA", @@ -2871,7 +2916,7 @@ "links": { "Homepage": "https://basicattentiontoken.org" }, - "marketcap_usd": 1948964720, + "marketcap_usd": 1359286971, "name": "Basic Attention Token", "network": "eth", "shortcut": "BAT", @@ -2890,7 +2935,7 @@ "links": { "Homepage": "https://getbabb.com" }, - "marketcap_usd": 32409775, + "marketcap_usd": 16712055, "name": "BABB", "network": "eth", "shortcut": "BAX", @@ -2967,7 +3012,7 @@ "links": { "Homepage": "https://bigbom.com" }, - "marketcap_usd": 199348, + "marketcap_usd": 119469, "name": "Bigbom", "network": "eth", "shortcut": "BBO", @@ -3065,7 +3110,7 @@ "Github": "https://github.com/VinceBCD/BCDiploma", "Homepage": "https://www.bcdiploma.com" }, - "marketcap_usd": 6427596, + "marketcap_usd": 4323403, "name": "Blockchain Certified Data Token", "network": "eth", "shortcut": "BCDT", @@ -3123,7 +3168,7 @@ "Github": "https://github.com/blockmason", "Homepage": "https://blockmason.io" }, - "marketcap_usd": 233307, + "marketcap_usd": 316544, "name": "BlockMason Credit Protocol Token", "network": "eth", "shortcut": "BCPT", @@ -3143,7 +3188,7 @@ "Github": "https://github.com/bitcv", "Homepage": "https://bitcv.one/" }, - "marketcap_usd": 274483, + "marketcap_usd": 175696, "name": "BitCapitalVendor Token", "network": "eth", "shortcut": "BCV", @@ -3242,7 +3287,7 @@ "Github": "https://github.com/Rentberry", "Homepage": "https://rentberry.com" }, - "marketcap_usd": 153948, + "marketcap_usd": 147616, "name": "Berry", "network": "eth", "shortcut": "BERRY", @@ -3340,7 +3385,7 @@ "links": { "Homepage": "https://bnktothefuture.com" }, - "marketcap_usd": 10566182, + "marketcap_usd": 9095802, "name": "BnkToTheFuture", "network": "eth", "shortcut": "BFT", @@ -3456,7 +3501,7 @@ "Github": "https://github.com/BitScreenerTech", "Homepage": "https://tokensale.bitscreener.com/" }, - "marketcap_usd": 1093614, + "marketcap_usd": 869663, "name": "Token BitScreenerToken", "network": "eth", "shortcut": "BITX", @@ -3475,7 +3520,7 @@ "links": { "Homepage": "https://www.bibox.com" }, - "marketcap_usd": 4251830, + "marketcap_usd": 0, "name": "Bibox Token", "network": "eth", "shortcut": "BIX", @@ -3632,7 +3677,7 @@ "Github": "https://github.com/BlueCrypto", "Homepage": "https://blueprotocol.com/" }, - "marketcap_usd": 1229197, + "marketcap_usd": 686677, "name": "Ethereum Blue", "network": "eth", "shortcut": "BLUE", @@ -3690,7 +3735,7 @@ "links": { "Homepage": "https://bluzelle.com" }, - "marketcap_usd": 78295875, + "marketcap_usd": 63575125, "name": "Bluzelle", "network": "eth", "shortcut": "BLZ", @@ -3729,7 +3774,7 @@ "links": { "Homepage": "https://www.bitmart.com" }, - "marketcap_usd": 61221969, + "marketcap_usd": 53196314, "name": "BitMart Token", "network": "eth", "shortcut": "BMX", @@ -3748,7 +3793,7 @@ "links": { "Homepage": "https://www.binance.com" }, - "marketcap_usd": 90547224093, + "marketcap_usd": 72574315643, "name": "Binance Coin", "network": "eth", "shortcut": "BNB", @@ -3807,7 +3852,7 @@ "Github": "https://github.com/bancorprotocol", "Homepage": "https://www.bancor.network" }, - "marketcap_usd": 819906062, + "marketcap_usd": 724022143, "name": "Bancor Network Token", "network": "eth", "shortcut": "BNT", @@ -3826,7 +3871,7 @@ "links": { "Homepage": "https://bounty0x.io" }, - "marketcap_usd": 333190, + "marketcap_usd": 192030, "name": "Bounty0x Token", "network": "eth", "shortcut": "BNTY", @@ -3845,7 +3890,7 @@ "links": { "Homepage": "https://bobsrepair.com" }, - "marketcap_usd": 1098725, + "marketcap_usd": 661689, "name": "Bob's repair", "network": "eth", "shortcut": "BOB", @@ -3922,7 +3967,7 @@ "links": { "Homepage": "https://bonpay.com" }, - "marketcap_usd": 16887, + "marketcap_usd": 16214, "name": "Bonpay", "network": "eth", "shortcut": "BON", @@ -3979,7 +4024,7 @@ "links": { "Homepage": "https://www.bouts.pro" }, - "marketcap_usd": 220658, + "marketcap_usd": 236897, "name": "BoutsPro", "network": "eth", "shortcut": "BOUTS", @@ -4076,7 +4121,7 @@ "Github": "https://github.com/breadwallet", "Homepage": "https://token.breadapp.com/en" }, - "marketcap_usd": 67547831, + "marketcap_usd": 25057824, "name": "Bread", "network": "eth", "shortcut": "BRD", @@ -4251,7 +4296,7 @@ "links": { "Homepage": "http://btclite.org" }, - "marketcap_usd": 121202, + "marketcap_usd": 17904, "name": "BTC Lite", "network": "eth", "shortcut": "BTCL", @@ -4408,7 +4453,7 @@ "links": { "Homepage": "https://www.bottos.org" }, - "marketcap_usd": 657057, + "marketcap_usd": 315803, "name": "Bottos", "network": "eth", "shortcut": "BTO", @@ -4466,7 +4511,7 @@ "links": { "Homepage": "https://biotron.io" }, - "marketcap_usd": 65776, + "marketcap_usd": 63158, "name": "Biotron", "network": "eth", "shortcut": "BTRN", @@ -4486,7 +4531,7 @@ "Github": "https://github.com/btuprotocol", "Homepage": "https://btu-protocol.com" }, - "marketcap_usd": 53253925, + "marketcap_usd": 34490452, "name": "BTU Protocol", "network": "eth", "shortcut": "BTU", @@ -4545,7 +4590,7 @@ "Github": "https://github.com/paxosglobal/busd-contract", "Homepage": "https://www.paxos.com/busd" }, - "marketcap_usd": 14644861569, + "marketcap_usd": 17553268623, "name": "Binance USD (BUSD)", "network": "eth", "shortcut": "BUSD", @@ -4622,7 +4667,7 @@ "links": { "Homepage": "https://bezant.io" }, - "marketcap_usd": 4077658, + "marketcap_usd": 822362, "name": "Bezant", "network": "eth", "shortcut": "BZNT", @@ -4662,7 +4707,7 @@ "Github": "https://github.com/cryptotwenty", "Homepage": "https://crypto20.com" }, - "marketcap_usd": 190396510, + "marketcap_usd": 157880605, "name": "Crypto20's Token", "network": "eth", "shortcut": "C20", @@ -4720,7 +4765,7 @@ "Github": "https://github.com/Global-Crypto-Alliance/call-token", "Homepage": "https://gcalliance.io" }, - "marketcap_usd": 78692, + "marketcap_usd": 60447, "name": "CALL token", "network": "eth", "shortcut": "CALL", @@ -4834,7 +4879,7 @@ "links": { "Homepage": "https://coin.cashbet.com" }, - "marketcap_usd": 10476145, + "marketcap_usd": 6881097, "name": "CashBet Coin", "network": "eth", "shortcut": "CBC", @@ -4950,7 +4995,7 @@ "links": { "Homepage": "https://ccore.io" }, - "marketcap_usd": 48916, + "marketcap_usd": 22978, "name": "Ccore", "network": "eth", "shortcut": "CCO", @@ -5027,7 +5072,7 @@ "links": { "Homepage": "https://www.ceek.com/" }, - "marketcap_usd": 511034767, + "marketcap_usd": 342139054, "name": "CEEK VR Token", "network": "eth", "shortcut": "CEEK", @@ -5047,7 +5092,7 @@ "Github": "https://github.com/celer-network", "Homepage": "https://www.celer.network/" }, - "marketcap_usd": 529481725, + "marketcap_usd": 396270900, "name": "CelerToken", "network": "eth", "shortcut": "CELR", @@ -5067,7 +5112,7 @@ "Github": "https://github.com/coinsuperapi", "Homepage": "https://www.coinsuper.com" }, - "marketcap_usd": 260555, + "marketcap_usd": 0, "name": "CEN", "network": "eth", "shortcut": "CEN", @@ -5086,7 +5131,7 @@ "links": { "Homepage": "https://www.centrality.ai" }, - "marketcap_usd": 214321151, + "marketcap_usd": 143136393, "name": "Centrality", "network": "eth", "shortcut": "CENNZ", @@ -5184,7 +5229,7 @@ "Github": "https://github.com/cache-token/cache-contract", "Homepage": "https://cache.gold" }, - "marketcap_usd": 5249589, + "marketcap_usd": 5488496, "name": "CACHE Gold", "network": "eth", "shortcut": "CGT", @@ -5242,7 +5287,7 @@ "links": { "Homepage": "https://swissborg.com" }, - "marketcap_usd": 617325926, + "marketcap_usd": 469959129, "name": "SwissBorg", "network": "eth", "shortcut": "CHSB", @@ -5275,32 +5320,13 @@ } ] }, - "erc20:eth:CIG": { - "address": "0x00380143129167395e8B4F0a35EDc1bC60E7cE65", - "links": { - "Homepage": "https://www.ciorigin.net/" - }, - "marketcap_usd": 0, - "name": "Clorigin", - "network": "eth", - "shortcut": "CIG", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:CIV": { "address": "0x37fE0f067FA808fFBDd12891C0858532CFE7361d", "links": { "Github": "https://github.com/CivilizationCIV", "Homepage": "https://civfund.org" }, - "marketcap_usd": 30478141, + "marketcap_usd": 29029032, "name": "Civilization", "network": "eth", "shortcut": "CIV", @@ -5475,7 +5501,7 @@ "links": { "Homepage": "https://coinloan.io" }, - "marketcap_usd": 74948465, + "marketcap_usd": 42375318, "name": "CoinLoan", "network": "eth", "shortcut": "CLT", @@ -5551,7 +5577,7 @@ "links": { "Homepage": "https://app.coinmerge.io/" }, - "marketcap_usd": 0, + "marketcap_usd": 3484745, "name": "Coin Merge", "network": "eth", "shortcut": "CMERGE", @@ -5589,7 +5615,7 @@ "links": { "Homepage": "https://cindicator.com" }, - "marketcap_usd": 23369288, + "marketcap_usd": 2053877, "name": "Cindicator", "network": "eth", "shortcut": "CND", @@ -5603,12 +5629,32 @@ } ] }, + "erc20:eth:CNDL": { + "address": "0xbc138bD20C98186CC0342C8e380953aF0cb48BA8", + "links": { + "Github": "https://GitHub.com/candleplatforms", + "Homepage": "https://candlelabs.org" + }, + "marketcap_usd": 0, + "name": "Candle", + "network": "eth", + "shortcut": "CNDL", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:CNN": { "address": "0x8713d26637CF49e1b6B4a7Ce57106AaBc9325343", "links": { "Homepage": "https://cnntoken.io" }, - "marketcap_usd": 350381, + "marketcap_usd": 340103, "name": "Content Neutrality Network", "network": "eth", "shortcut": "CNN", @@ -5667,7 +5713,7 @@ "Github": "https://github.com/cobinhood", "Homepage": "https://cobinhood.com" }, - "marketcap_usd": 204918, + "marketcap_usd": 196754, "name": "Cobinhood Token", "network": "eth", "shortcut": "COB", @@ -5707,7 +5753,7 @@ "Github": "https://github.com/coinfi", "Homepage": "https://www.coinfi.com" }, - "marketcap_usd": 792359, + "marketcap_usd": 522082, "name": "CoinFi Token", "network": "eth", "shortcut": "COFI", @@ -5747,7 +5793,7 @@ "Github": "https://github.com/compound-finance", "Homepage": "https://compound.finance" }, - "marketcap_usd": 1447937034, + "marketcap_usd": 956428162, "name": "Compound", "network": "eth", "shortcut": "COMP", @@ -5805,7 +5851,7 @@ "Github": "https://github.com/coti-io", "Homepage": "https://coti.io" }, - "marketcap_usd": 365514619, + "marketcap_usd": 306047919, "name": "COTI", "network": "eth", "shortcut": "COTI", @@ -5882,7 +5928,7 @@ "links": { "Homepage": "http://www.cpchain.io" }, - "marketcap_usd": 2307211, + "marketcap_usd": 2621399, "name": "CPChain", "network": "eth", "shortcut": "CPC", @@ -6135,7 +6181,7 @@ "links": { "Homepage": "https://credits.com/en" }, - "marketcap_usd": 5630400, + "marketcap_usd": 6876327, "name": "Credits", "network": "eth", "shortcut": "CS", @@ -6253,7 +6299,7 @@ "Github": "https://github.com/cartesi", "Homepage": "https://cartesi.io" }, - "marketcap_usd": 389652939, + "marketcap_usd": 225142914, "name": "Cartesi Token", "network": "eth", "shortcut": "CTSI", @@ -6349,7 +6395,7 @@ "links": { "Homepage": "https://www.civic.com" }, - "marketcap_usd": 242523896, + "marketcap_usd": 239825449, "name": "Civic", "network": "eth", "shortcut": "CVC", @@ -6388,7 +6434,7 @@ "links": { "Homepage": "http://www.cybervein.org" }, - "marketcap_usd": 5817656, + "marketcap_usd": 4586220, "name": "CyberVein", "network": "eth", "shortcut": "CVT", @@ -6428,7 +6474,7 @@ "Github": "https://github.com/cargoxio", "Homepage": "https://cargox.io" }, - "marketcap_usd": 27268249, + "marketcap_usd": 56860188, "name": "CargoX", "network": "eth", "shortcut": "CXO", @@ -6486,7 +6532,7 @@ "links": { "Homepage": "https://cybermusic.io" }, - "marketcap_usd": 91573, + "marketcap_usd": 43262, "name": "CyberMusic", "network": "eth", "shortcut": "CYMT", @@ -6563,7 +6609,7 @@ "links": { "Homepage": "https://dacsee.io/#" }, - "marketcap_usd": 752807, + "marketcap_usd": 722838, "name": "DACSEE", "network": "eth", "shortcut": "DACS", @@ -6596,16 +6642,16 @@ } ] }, - "erc20:eth:DAI": { - "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "erc20:eth:DAF": { + "address": "0x1d0198829cBA768E4Ef2f762CD82842Bba3e3458", "links": { - "Github": "https://github.com/makerdao", - "Homepage": "https://makerdao.com" + "Github": "https://github.com/daftoken/DAF", + "Homepage": "https://daftoken.io" }, - "marketcap_usd": 9369070458, - "name": "Dai Stablecoin v2.0", + "marketcap_usd": 0, + "name": "Diamonds are Forever", "network": "eth", - "shortcut": "DAI", + "shortcut": "DAF", "t1_enabled": "yes", "t2_enabled": "yes", "type": "erc20", @@ -6699,7 +6745,7 @@ "links": { "Homepage": "https://www.datx.co" }, - "marketcap_usd": 283171, + "marketcap_usd": 59406, "name": "DATx", "network": "eth", "shortcut": "DATX", @@ -6719,7 +6765,7 @@ "Github": "https://github.com/DAVFoundation", "Homepage": "https://dav.network/" }, - "marketcap_usd": 1485738, + "marketcap_usd": 1769948, "name": "DAV Token", "network": "eth", "shortcut": "DAV", @@ -6738,7 +6784,7 @@ "links": { "Homepage": "https://www.daex.io" }, - "marketcap_usd": 2851189, + "marketcap_usd": 2349711, "name": "DAEX", "network": "eth", "shortcut": "DAX", @@ -6777,7 +6823,7 @@ "Github": "https://github.com/chronologic", "Homepage": "https://chronologic.network" }, - "marketcap_usd": 174746, + "marketcap_usd": 142319, "name": "ChronoLogic DAY", "network": "eth", "shortcut": "DAY", @@ -6796,7 +6842,7 @@ "links": { "Homepage": "https://www.decent.bet" }, - "marketcap_usd": 677080, + "marketcap_usd": 451674, "name": "DecentBet", "network": "eth", "shortcut": "DBET", @@ -6895,7 +6941,7 @@ "Github": "https://github.com/Dentacoin", "Homepage": "https://dentacoin.com" }, - "marketcap_usd": 12880880, + "marketcap_usd": 7026118, "name": "Dentacoin", "network": "eth", "shortcut": "DCN", @@ -6934,7 +6980,7 @@ "links": { "Homepage": "https://debitum.network/" }, - "marketcap_usd": 771981, + "marketcap_usd": 1145268, "name": "DEBITUM", "network": "eth", "shortcut": "DEB", @@ -6992,7 +7038,7 @@ "links": { "Homepage": "https://www.dentwireless.com" }, - "marketcap_usd": 451884034, + "marketcap_usd": 337010455, "name": "DENT", "network": "eth", "shortcut": "DENT", @@ -7050,7 +7096,7 @@ "Github": "https://github.com/dforcenetwork", "Homepage": "https://dforce.network" }, - "marketcap_usd": 42749451, + "marketcap_usd": 35765039, "name": "dForce Platform Token", "network": "eth", "shortcut": "DF", @@ -7064,25 +7110,6 @@ } ] }, - "erc20:eth:DGD": { - "address": "0xE0B7927c4aF23765Cb51314A0E0521A9645F0E2A", - "links": { - "Homepage": "https://digix.global/" - }, - "marketcap_usd": 60349707, - "name": "Digix DAO", - "network": "eth", - "shortcut": "DGD", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:DGPT": { "address": "0xf6cFe53d6FEbaEEA051f400ff5fc14F0cBBDacA1", "links": { @@ -7129,7 +7156,7 @@ "Github": "https://github.com/DigixGlobal", "Homepage": "https://digix.global" }, - "marketcap_usd": 1710433, + "marketcap_usd": 1346529, "name": "Digix Gold Token", "network": "eth", "shortcut": "DGX", @@ -7207,7 +7234,7 @@ "links": { "Homepage": "https://inmediate.io" }, - "marketcap_usd": 505953, + "marketcap_usd": 860437, "name": "Digital Insurance Token", "network": "eth", "shortcut": "DIT", @@ -7245,7 +7272,7 @@ "links": { "Homepage": "https://www.agrello.org" }, - "marketcap_usd": 257403, + "marketcap_usd": 430793, "name": "Agrello", "network": "eth", "shortcut": "DLT", @@ -7265,7 +7292,7 @@ "Github": "https://github.com/suntechsoft/dmarket-smartcontract", "Homepage": "https://dmarket.com" }, - "marketcap_usd": 964933, + "marketcap_usd": 782420, "name": "DMarket Token", "network": "eth", "shortcut": "DMT", @@ -7304,7 +7331,7 @@ "Github": "https://github.com/district0x", "Homepage": "https://district0x.io" }, - "marketcap_usd": 84334753, + "marketcap_usd": 52006400, "name": "District0x Network Token", "network": "eth", "shortcut": "DNT", @@ -7400,7 +7427,7 @@ "links": { "Homepage": "https://dovu.io" }, - "marketcap_usd": 10329742, + "marketcap_usd": 38621154, "name": "Dovu", "network": "eth", "shortcut": "DOV", @@ -7459,7 +7486,7 @@ "Github": "https://github.com/dragonchain/dragonchain", "Homepage": "https://dragonchain.com" }, - "marketcap_usd": 29417720, + "marketcap_usd": 23845398, "name": "Dragon", "network": "eth", "shortcut": "DRGN", @@ -7497,7 +7524,7 @@ "links": { "Homepage": "https://token.domraider.com" }, - "marketcap_usd": 480809, + "marketcap_usd": 339796, "name": "DomRaider", "network": "eth", "shortcut": "DRT", @@ -7596,7 +7623,7 @@ "Github": "https://github.com/dethertech", "Homepage": "https://dether.io" }, - "marketcap_usd": 699152, + "marketcap_usd": 513776, "name": "dether", "network": "eth", "shortcut": "DTH", @@ -7634,7 +7661,7 @@ "links": { "Homepage": "https://datarius.io" }, - "marketcap_usd": 28916, + "marketcap_usd": 9039, "name": "Datarius Credit", "network": "eth", "shortcut": "DTRC", @@ -7847,7 +7874,7 @@ "links": { "Homepage": "https://omnitude.tech" }, - "marketcap_usd": 606581, + "marketcap_usd": 582108, "name": "Omnitude", "network": "eth", "shortcut": "ECOM", @@ -7885,7 +7912,7 @@ "links": { "Homepage": "https://edgeless.io" }, - "marketcap_usd": 5360106, + "marketcap_usd": 4578145, "name": "Edgeless", "network": "eth", "shortcut": "EDG", @@ -7944,7 +7971,7 @@ "Github": "https://github.com/EndorCoin", "Homepage": "https://www.endor.com" }, - "marketcap_usd": 1816225, + "marketcap_usd": 836813, "name": "Endor Protocol Token", "network": "eth", "shortcut": "EDR", @@ -8004,7 +8031,7 @@ "Github": "https://github.com/egretia", "Homepage": "https://www.egretia.io" }, - "marketcap_usd": 4060081, + "marketcap_usd": 3219208, "name": "Egretia Token", "network": "eth", "shortcut": "EGT", @@ -8062,7 +8089,7 @@ "links": { "Homepage": "https://echolink.info" }, - "marketcap_usd": 206157, + "marketcap_usd": 131515, "name": "EchoLink", "network": "eth", "shortcut": "EKO", @@ -8100,7 +8127,7 @@ "links": { "Homepage": "https://electrify.asia" }, - "marketcap_usd": 780886, + "marketcap_usd": 486257, "name": "Electrify.Asia", "network": "eth", "shortcut": "ELEC", @@ -8120,7 +8147,7 @@ "Github": "https://github.com/aelfProject", "Homepage": "https://aelf.io/" }, - "marketcap_usd": 213246479, + "marketcap_usd": 219834487, "name": "ELF Token", "network": "eth", "shortcut": "ELF", @@ -8159,7 +8186,7 @@ "Github": "https://github.com/eltcoin", "Homepage": "http://www.eltcoin.tech/" }, - "marketcap_usd": 65469, + "marketcap_usd": 43446, "name": "ELTCOIN", "network": "eth", "shortcut": "ELTCOIN", @@ -8179,7 +8206,7 @@ "Github": "https://github.com/Elysian-ELY", "Homepage": "https://elycoin.io" }, - "marketcap_usd": 213798, + "marketcap_usd": 101340, "name": "ELYCOIN", "network": "eth", "shortcut": "ELY", @@ -8317,7 +8344,7 @@ "Github": "https://github.com/enigmampc", "Homepage": "https://enigma.co/" }, - "marketcap_usd": 1081514, + "marketcap_usd": 517011, "name": "Enigma", "network": "eth", "shortcut": "ENG", @@ -8356,7 +8383,7 @@ "Github": "https://github.com/enjin/contracts", "Homepage": "https://enjincoin.io" }, - "marketcap_usd": 2594571899, + "marketcap_usd": 1572753631, "name": "ENJIN", "network": "eth", "shortcut": "ENJ", @@ -8376,7 +8403,7 @@ "Github": "https://github.com/Enecuum", "Homepage": "https://enecuum.com" }, - "marketcap_usd": 14305265, + "marketcap_usd": 7211597, "name": "Enecuum", "network": "eth", "shortcut": "ENQ", @@ -8493,7 +8520,7 @@ "links": { "Homepage": "https://eroscoin.org" }, - "marketcap_usd": 93107, + "marketcap_usd": 89398, "name": "Eroscoin", "network": "eth", "shortcut": "ERO", @@ -8610,7 +8637,7 @@ "links": { "Homepage": "https://www.etgproject.org" }, - "marketcap_usd": 415678, + "marketcap_usd": 335145, "name": "Ethereum Gold", "network": "eth", "shortcut": "ETG", @@ -8747,7 +8774,7 @@ "Github": "https://github.com/stasisnet", "Homepage": "https://stasis.net" }, - "marketcap_usd": 112050329, + "marketcap_usd": 137660532, "name": "STASIS EURS", "network": "eth", "shortcut": "EURS", @@ -8785,7 +8812,7 @@ "links": { "Homepage": "https://eventchain.io" }, - "marketcap_usd": 287550, + "marketcap_usd": 125334, "name": "EventChain", "network": "eth", "shortcut": "EVC", @@ -8824,7 +8851,7 @@ "Github": "https://github.com/devery", "Homepage": "https://devery.io" }, - "marketcap_usd": 145606, + "marketcap_usd": 89027, "name": "Devery", "network": "eth", "shortcut": "EVE", @@ -8844,7 +8871,7 @@ "Github": "https://github.com/evedo-co", "Homepage": "https://www.evedo.co" }, - "marketcap_usd": 1503965, + "marketcap_usd": 1106088, "name": "Evedo Token", "network": "eth", "shortcut": "EVED", @@ -8903,7 +8930,7 @@ "links": { "Homepage": "https://everex.io " }, - "marketcap_usd": 4276177, + "marketcap_usd": 500074, "name": "Everex", "network": "eth", "shortcut": "EVX", @@ -9001,7 +9028,7 @@ "links": { "Homepage": "https://exrnchain.com" }, - "marketcap_usd": 2803681, + "marketcap_usd": 3380922, "name": "EXRNchain", "network": "eth", "shortcut": "EXRN", @@ -9117,7 +9144,7 @@ "links": { "Homepage": "https://tokensale.faceter.io" }, - "marketcap_usd": 762218, + "marketcap_usd": 632167, "name": "Faceter", "network": "eth", "shortcut": "FACE", @@ -9215,7 +9242,7 @@ "links": { "Homepage": "https://friendz.io" }, - "marketcap_usd": 675785, + "marketcap_usd": 432362, "name": "Friendz", "network": "eth", "shortcut": "FDZ", @@ -9353,7 +9380,7 @@ "links": { "Homepage": "https://www.flixxo.com" }, - "marketcap_usd": 4390534, + "marketcap_usd": 538774, "name": "Flixxo", "network": "eth", "shortcut": "FLIXX", @@ -9372,7 +9399,7 @@ "links": { "Homepage": "https://firelotto.io" }, - "marketcap_usd": 106620, + "marketcap_usd": 200286, "name": "Fire Lotto", "network": "eth", "shortcut": "FLOT", @@ -9470,7 +9497,7 @@ "Github": "https://github.com/civitas-fundamenta", "Homepage": "https://fundamenta.network" }, - "marketcap_usd": 267703, + "marketcap_usd": 115460, "name": "Fundamenta", "network": "eth", "shortcut": "FMTA", @@ -9548,7 +9575,7 @@ "Github": "https://github.com/f-o-a-m", "Homepage": "http://foam.space" }, - "marketcap_usd": 17092199, + "marketcap_usd": 17555431, "name": "FOAM Token", "network": "eth", "shortcut": "FOAM", @@ -9606,7 +9633,7 @@ "links": { "Homepage": "https://www.fota.io" }, - "marketcap_usd": 198406, + "marketcap_usd": 0, "name": "Fortuna", "network": "eth", "shortcut": "FOTA", @@ -9625,7 +9652,7 @@ "links": { "Homepage": "https://shapeshift.com" }, - "marketcap_usd": 73707491, + "marketcap_usd": 92814510, "name": "FOX", "network": "eth", "shortcut": "FOX", @@ -9761,7 +9788,7 @@ "links": { "Homepage": "https://fanstime.org" }, - "marketcap_usd": 316267, + "marketcap_usd": 186911, "name": "FansTime", "network": "eth", "shortcut": "FTI", @@ -9781,7 +9808,7 @@ "Github": "https://github.com/Fantom-foundation/", "Homepage": "https://fantom.foundation/" }, - "marketcap_usd": 5891754689, + "marketcap_usd": 3741341758, "name": "Fantom Token", "network": "eth", "shortcut": "FTM", @@ -9839,7 +9866,7 @@ "links": { "Homepage": "https://www.fintrux.com" }, - "marketcap_usd": 1081106, + "marketcap_usd": 1163179, "name": "FintruX Network", "network": "eth", "shortcut": "FTX", @@ -9859,7 +9886,7 @@ "Github": "https://github.com/futuraxproject", "Homepage": "https://futurax.global" }, - "marketcap_usd": 74338, + "marketcap_usd": 19967, "name": "FUTURAX", "network": "eth", "shortcut": "FTXT", @@ -9879,7 +9906,7 @@ "Github": "https://github.com/etherparty", "Homepage": "https://etherparty.io" }, - "marketcap_usd": 590788, + "marketcap_usd": 376761, "name": "Etherparty FUEL", "network": "eth", "shortcut": "FUEL", @@ -9898,7 +9925,7 @@ "links": { "Homepage": "https://funfair.io" }, - "marketcap_usd": 133333832, + "marketcap_usd": 128187550, "name": "Funfair", "network": "eth", "shortcut": "FUN", @@ -9917,7 +9944,7 @@ "links": { "Homepage": "https://fuzex.co" }, - "marketcap_usd": 181502, + "marketcap_usd": 306830, "name": "FuzeX", "network": "eth", "shortcut": "FXT", @@ -9975,7 +10002,7 @@ "links": { "Homepage": "https://flyp.me" }, - "marketcap_usd": 1248804, + "marketcap_usd": 1393261, "name": "FlypMe", "network": "eth", "shortcut": "FYP", @@ -9994,7 +10021,7 @@ "links": { "Homepage": "https://www.fyooz.io/" }, - "marketcap_usd": 349095, + "marketcap_usd": 108057, "name": "Fyooz", "network": "eth", "shortcut": "FYZ", @@ -10034,7 +10061,7 @@ "Github": "https://github.com/gluwa/Creditcoin", "Homepage": "https://creditcoinfoundation.org" }, - "marketcap_usd": 1418784076, + "marketcap_usd": 0, "name": "Creditcoin Token", "network": "eth", "shortcut": "G-CRE", @@ -10074,7 +10101,7 @@ "Github": "https://github.com/gamecredits-project", "Homepage": "https://www.gamecredits.org" }, - "marketcap_usd": 30648608, + "marketcap_usd": 17131562, "name": "GAME Credits", "network": "eth", "shortcut": "GAME", @@ -10113,7 +10140,7 @@ "Github": "https://github.com/GateNet-IO/gate-erc20-token", "Homepage": "https://gatetoken.io/" }, - "marketcap_usd": 15048246, + "marketcap_usd": 9503925, "name": "GATE Token", "network": "eth", "shortcut": "GATE", @@ -10309,7 +10336,7 @@ "Github": "https://github.com/Governor-DAO", "Homepage": "https://www.governordao.org" }, - "marketcap_usd": 2621197, + "marketcap_usd": 1624074, "name": "Governor DAO", "network": "eth", "shortcut": "GDAO", @@ -10387,7 +10414,7 @@ "links": { "Homepage": "https://gems.org" }, - "marketcap_usd": 374450, + "marketcap_usd": 248689, "name": "Gems", "network": "eth", "shortcut": "GEM", @@ -10407,7 +10434,7 @@ "Github": "https://github.com/daostack", "Homepage": "https://daostack.io" }, - "marketcap_usd": 2921614, + "marketcap_usd": 1650573, "name": "DAOstack", "network": "eth", "shortcut": "GEN", @@ -10446,7 +10473,7 @@ "Github": "https://github.com/Getprotocol", "Homepage": "http://www.get-protocol.io" }, - "marketcap_usd": 25503387, + "marketcap_usd": 28917418, "name": "GET Protocol", "network": "eth", "shortcut": "GET", @@ -10504,7 +10531,7 @@ "links": { "Homepage": "https://gamerhash.io/" }, - "marketcap_usd": 32488794, + "marketcap_usd": 22948571, "name": "GamerCoin", "network": "eth", "shortcut": "GHX", @@ -10621,7 +10648,7 @@ "links": { "Homepage": "https://gnosis.pm" }, - "marketcap_usd": 712990500, + "marketcap_usd": 939179794, "name": "Gnosis", "network": "eth", "shortcut": "GNO", @@ -10635,32 +10662,12 @@ } ] }, - "erc20:eth:GNT": { - "address": "0xa74476443119A942dE498590Fe1f2454d7D4aC0d", - "links": { - "Github": "https://github.com/golemfactory/golem", - "Homepage": "https://golem.network" - }, - "marketcap_usd": 0, - "name": "Golem", - "network": "eth", - "shortcut": "GNT", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:GNX": { "address": "0x6EC8a24CaBdc339A06a172F8223ea557055aDAa5", "links": { "Homepage": "https://genaro.network" }, - "marketcap_usd": 9337414, + "marketcap_usd": 11298673, "name": "Genaro Network", "network": "eth", "shortcut": "GNX", @@ -10719,7 +10726,7 @@ "links": { "Homepage": "https://gonetwork.co/index.html" }, - "marketcap_usd": 156499, + "marketcap_usd": 105119, "name": "GoNetwork", "network": "eth", "shortcut": "GOT", @@ -10739,7 +10746,7 @@ "Github": "https://github.com/coti-io/cvi-contracts", "Homepage": "https://cvi.finance" }, - "marketcap_usd": 11974435, + "marketcap_usd": 13380803, "name": "GOVI", "network": "eth", "shortcut": "GOVI", @@ -10777,7 +10784,7 @@ "links": { "Homepage": "http://gridplus.io" }, - "marketcap_usd": 66612085, + "marketcap_usd": 70803692, "name": "Grid+", "network": "eth", "shortcut": "GRID", @@ -10856,7 +10863,7 @@ "Github": "https://github.com/graphprotocol", "Homepage": "https://thegraph.com" }, - "marketcap_usd": 3460929520, + "marketcap_usd": 2284562024, "name": "Graph Token", "network": "eth", "shortcut": "GRT", @@ -10875,7 +10882,7 @@ "links": { "Homepage": "https://www.gsc.social" }, - "marketcap_usd": 2481415, + "marketcap_usd": 1609629, "name": "Global Social Chain", "network": "eth", "shortcut": "GSC", @@ -10914,7 +10921,7 @@ "Github": "https://github.com/GameLeLe", "Homepage": "https://game.com" }, - "marketcap_usd": 2217564, + "marketcap_usd": 1434696, "name": "GTC Token", "network": "eth", "shortcut": "GTC", @@ -10954,7 +10961,7 @@ "Github": "https://github.com/GIFTO-io", "Homepage": "https://gifto.io/" }, - "marketcap_usd": 47114932, + "marketcap_usd": 42042083, "name": "Gifto", "network": "eth", "shortcut": "GTO", @@ -11007,32 +11014,13 @@ } ] }, - "erc20:eth:GUP": { - "address": "0xf7B098298f7C69Fc14610bf71d5e02c60792894C", - "links": { - "Homepage": "https://matchpool.co" - }, - "marketcap_usd": 0, - "name": "Matchpool", - "network": "eth", - "shortcut": "GUP", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:GVT": { "address": "0x103c3A209da59d3E7C4A89307e66521e081CFDF0", "links": { "Github": "https://github.com/GenesisVision", "Homepage": "https://genesis.vision" }, - "marketcap_usd": 1567098, + "marketcap_usd": 1547046, "name": "Genesis Vision", "network": "eth", "shortcut": "GVT", @@ -11208,7 +11196,7 @@ "links": { "Homepage": "https://www.showhand.io" }, - "marketcap_usd": 50041, + "marketcap_usd": 42696, "name": "ShowHand", "network": "eth", "shortcut": "HAND", @@ -11284,7 +11272,7 @@ "links": { "Homepage": "https://heartbout.com" }, - "marketcap_usd": 133359, + "marketcap_usd": 51218, "name": "HeartBout", "network": "eth", "shortcut": "HB", @@ -11420,7 +11408,7 @@ "Github": "https://github.com/bitcoinHEX", "Homepage": "https://hex.win" }, - "marketcap_usd": 51558349387, + "marketcap_usd": 26171009572, "name": "HEX", "network": "eth", "shortcut": "HEX", @@ -11614,7 +11602,7 @@ "links": { "Homepage": "https://humaniq.com" }, - "marketcap_usd": 1506104, + "marketcap_usd": 1504065, "name": "Humaniq", "network": "eth", "shortcut": "HMQ", @@ -11712,7 +11700,7 @@ "Github": "https://github.com/Holo-Host", "Homepage": "https://holo.host/" }, - "marketcap_usd": 1482231263, + "marketcap_usd": 1119184330, "name": "Holo Token", "network": "eth", "shortcut": "HOT (Holo)", @@ -11731,7 +11719,7 @@ "links": { "Homepage": "https://thehydrofoundation.com/" }, - "marketcap_usd": 4548242, + "marketcap_usd": 3978384, "name": "Hydro Protocol", "network": "eth", "shortcut": "HOT (Hydro)", @@ -11769,7 +11757,7 @@ "links": { "Homepage": "https://www.hbg.com" }, - "marketcap_usd": 1565083688, + "marketcap_usd": 1468925558, "name": "Huobi Token", "network": "eth", "shortcut": "HT", @@ -11888,7 +11876,7 @@ "Github": "https://github.com/HiveProjectLTD", "Homepage": "https://www.hiveterminal.com" }, - "marketcap_usd": 8950532, + "marketcap_usd": 6365807, "name": "Hiveterminal Token", "network": "eth", "shortcut": "HVN", @@ -12043,7 +12031,7 @@ "links": { "Homepage": "https://www.everest.org" }, - "marketcap_usd": 26217330, + "marketcap_usd": 27529736, "name": "Everest (ID)", "network": "eth", "shortcut": "ID", @@ -12101,7 +12089,7 @@ "Github": "https://github.com/rupiah-token/", "Homepage": "https://www.rupiahtoken.com" }, - "marketcap_usd": 8010073, + "marketcap_usd": 15045987, "name": "Rupiah Token", "network": "eth", "shortcut": "IDRT", @@ -12120,7 +12108,7 @@ "links": { "Homepage": "https://investfeed.com" }, - "marketcap_usd": 95416, + "marketcap_usd": 91618, "name": "InvestFeed", "network": "eth", "shortcut": "IFT", @@ -12139,7 +12127,7 @@ "links": { "Homepage": "http://igtoken.net" }, - "marketcap_usd": 173334, + "marketcap_usd": 17747, "name": "IGToken", "network": "eth", "shortcut": "IG", @@ -12178,7 +12166,7 @@ "links": { "Homepage": "https://ihtcoin.com" }, - "marketcap_usd": 515902, + "marketcap_usd": 416166, "name": "I HOUSE TOKEN", "network": "eth", "shortcut": "IHT", @@ -12255,7 +12243,7 @@ "links": { "Homepage": "https://indorse.io" }, - "marketcap_usd": 1198175, + "marketcap_usd": 533585, "name": "Indorse", "network": "eth", "shortcut": "IND", @@ -12489,7 +12477,7 @@ "Github": "https://github.com/iqeon", "Homepage": "https://iqeon.io/" }, - "marketcap_usd": 16747023, + "marketcap_usd": 13037074, "name": "IQeon", "network": "eth", "shortcut": "IQN", @@ -12549,7 +12537,7 @@ "Github": "https://github.com/IoTChainCode", "Homepage": "https://iotchain.io/" }, - "marketcap_usd": 3251342, + "marketcap_usd": 2366654, "name": "IoT Chain", "network": "eth", "shortcut": "ITC", @@ -12647,7 +12635,7 @@ "links": { "Homepage": "https://www.insurex.co" }, - "marketcap_usd": 182485, + "marketcap_usd": 334369, "name": "InsureX", "network": "eth", "shortcut": "IXT", @@ -12706,7 +12694,7 @@ "Github": "https://github.com/TokyoToken/JasmyCoin", "Homepage": "https://jasmy.co.jp" }, - "marketcap_usd": 416113159, + "marketcap_usd": 166291719, "name": "JasmyCoin", "network": "eth", "shortcut": "JASMY", @@ -12803,7 +12791,7 @@ "Github": "https://github.com/JobchainOfficial", "Homepage": "https://www.jobchain.com" }, - "marketcap_usd": 5643909, + "marketcap_usd": 5030010, "name": "Jobchain", "network": "eth", "shortcut": "JOB", @@ -12880,7 +12868,7 @@ "links": { "Homepage": "http://www.kan.land" }, - "marketcap_usd": 19042656, + "marketcap_usd": 20025114, "name": "BitKan", "network": "eth", "shortcut": "KAN", @@ -12914,25 +12902,6 @@ } ] }, - "erc20:eth:KC": { - "address": "0x0D6DD9f68d24EC1d5fE2174f3EC8DAB52B52BaF5", - "links": { - "Homepage": "https://www.kmcc.io" - }, - "marketcap_usd": 0, - "name": "KMCC", - "network": "eth", - "shortcut": "KC", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:KIN": { "address": "0x818Fc6C2Ec5986bc6E2CBf00939d90556aB12ce5", "links": { @@ -12958,7 +12927,7 @@ "links": { "Homepage": "https://kindads.io" }, - "marketcap_usd": 46610, + "marketcap_usd": 20831, "name": "Kind Ads Token", "network": "eth", "shortcut": "KIND", @@ -13016,7 +12985,7 @@ "links": { "Homepage": "https://kanadecoin.com" }, - "marketcap_usd": 1584958, + "marketcap_usd": 1403880, "name": "KanadeCoin", "network": "eth", "shortcut": "KNDC", @@ -13094,7 +13063,7 @@ "Github": "https://github.com/Cryptense/", "Homepage": "https://kryll.io/" }, - "marketcap_usd": 53743071, + "marketcap_usd": 37600227, "name": "Kryll", "network": "eth", "shortcut": "KRL", @@ -13172,7 +13141,7 @@ "links": { "Homepage": "https://ico.kuende.com" }, - "marketcap_usd": 1002755, + "marketcap_usd": 134981, "name": "Kuende Token", "network": "eth", "shortcut": "KUE", @@ -13191,7 +13160,7 @@ "links": { "Homepage": "https://4new.io" }, - "marketcap_usd": 122828, + "marketcap_usd": 98874, "name": "4NEW", "network": "eth", "shortcut": "KWATT", @@ -13249,7 +13218,7 @@ "Github": "https://github.com/latoken", "Homepage": "https://latoken.com/" }, - "marketcap_usd": 59144517, + "marketcap_usd": 42127219, "name": "LATOKEN", "network": "eth", "shortcut": "LA", @@ -13326,7 +13295,7 @@ "links": { "Homepage": "https://www.mycred.io" }, - "marketcap_usd": 3934043, + "marketcap_usd": 3076402, "name": "Cred", "network": "eth", "shortcut": "LBA", @@ -13345,7 +13314,7 @@ "links": { "Homepage": "https://www.localcoinswap.com" }, - "marketcap_usd": 730109, + "marketcap_usd": 914519, "name": "LocalCoinSwap", "network": "eth", "shortcut": "LCS", @@ -13636,7 +13605,7 @@ "links": { "Homepage": "https://link.smartcontract.com" }, - "marketcap_usd": 10460028276, + "marketcap_usd": 8099857995, "name": "Chainlink", "network": "eth", "shortcut": "LINK (Chainlink)", @@ -13694,7 +13663,7 @@ "Github": "https://github.com/GNYIO", "Homepage": "https://www.gny.io/lisk" }, - "marketcap_usd": 2646572, + "marketcap_usd": 846477, "name": "Lisk Machine Learning", "network": "eth", "shortcut": "LML", @@ -13714,7 +13683,7 @@ "Github": "https://github.com/LunchMoneyToken", "Homepage": "https://www.lunchmoney.io/" }, - "marketcap_usd": 397425, + "marketcap_usd": 346714, "name": "Lunch Money", "network": "eth", "shortcut": "LMY", @@ -13734,7 +13703,7 @@ "Github": "https://github.com/lendingblock", "Homepage": "https://lendingblock.com" }, - "marketcap_usd": 0, + "marketcap_usd": 2032163, "name": "Lendingblock", "network": "eth", "shortcut": "LND", @@ -13792,7 +13761,7 @@ "links": { "Homepage": "https://www.locuschain.com" }, - "marketcap_usd": 27170024, + "marketcap_usd": 62574841, "name": "Locus Chain", "network": "eth", "shortcut": "LOCUS", @@ -13850,7 +13819,7 @@ "Github": "github.com/loomnetwork/", "Homepage": "https://loomx.io" }, - "marketcap_usd": 92834348, + "marketcap_usd": 100222757, "name": "LOOM", "network": "eth", "shortcut": "LOOM", @@ -13870,7 +13839,7 @@ "Github": "https://github.com/livepeer", "Homepage": "https://livepeer.org/" }, - "marketcap_usd": 916865321, + "marketcap_usd": 639484672, "name": "Livepeer Token", "network": "eth", "shortcut": "LPT", @@ -13909,7 +13878,7 @@ "Github": "https://github.com/loopring", "Homepage": "https://loopring.org" }, - "marketcap_usd": 3033270148, + "marketcap_usd": 1693460841, "name": "Loopring", "network": "eth", "shortcut": "LRC", @@ -13943,6 +13912,26 @@ } ] }, + "erc20:eth:LUCHOW": { + "address": "0xA5Ef74068d04ba0809B7379dD76Af5Ce34Ab7C57", + "links": { + "Github": "https://github.com/lunachoww/contract", + "Homepage": "https://lunachow.com" + }, + "marketcap_usd": 0, + "name": "LunaChow", + "network": "eth", + "shortcut": "LUCHOW", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:LUCK": { "address": "0xFB12e3CcA983B9f59D90912Fd17F8D745A8B2953", "links": { @@ -13987,7 +13976,7 @@ "Github": "https://github.com/lunyr", "Homepage": "https://lunyr.com" }, - "marketcap_usd": 290992, + "marketcap_usd": 127603, "name": "Lunyr", "network": "eth", "shortcut": "LUN", @@ -14105,7 +14094,7 @@ "Github": "https://github.com/decentraland", "Homepage": "https://decentraland.org" }, - "marketcap_usd": 6768470014, + "marketcap_usd": 5096245749, "name": "Decentraland MANA", "network": "eth", "shortcut": "MANA", @@ -14143,7 +14132,7 @@ "links": { "Homepage": "https://midasprotocol.io/" }, - "marketcap_usd": 586663, + "marketcap_usd": 132760, "name": "MIDAS PROTOCOL", "network": "eth", "shortcut": "MAS", @@ -14162,7 +14151,7 @@ "links": { "Homepage": "https://polygon.technology/" }, - "marketcap_usd": 19946558020, + "marketcap_usd": 13214060845, "name": "Matic Token", "network": "eth", "shortcut": "MATIC", @@ -14259,7 +14248,7 @@ "links": { "Homepage": "https://moedaseeds.com" }, - "marketcap_usd": 10640778, + "marketcap_usd": 8679216, "name": "Moeda Loyalty Points", "network": "eth", "shortcut": "MDA", @@ -14278,7 +14267,7 @@ "links": { "Homepage": "https://www.mdt.co" }, - "marketcap_usd": 97017381, + "marketcap_usd": 40175567, "name": "Measurable Data Token", "network": "eth", "shortcut": "MDT", @@ -14311,6 +14300,25 @@ } ] }, + "erc20:eth:MEDCASH": { + "address": "0x6652Fa201B6BBBC0b5b0aD3f5702b2B9849cc830", + "links": { + "Homepage": "https://medxchange.io" + }, + "marketcap_usd": 0, + "name": "MEDCASH", + "network": "eth", + "shortcut": "MEDCASH", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:MEDX": { "address": "0xfd1e80508F243E64CE234eA88A5Fd2827c71D4b7", "links": { @@ -14335,7 +14343,7 @@ "links": { "Homepage": "https://dontbuymeme.com" }, - "marketcap_usd": 16498163, + "marketcap_usd": 9462776, "name": "Meme", "network": "eth", "shortcut": "MEME", @@ -14394,7 +14402,7 @@ "links": { "Homepage": "https://www.metronome.io" }, - "marketcap_usd": 62753865, + "marketcap_usd": 37337103, "name": "Metronome", "network": "eth", "shortcut": "MET", @@ -14413,7 +14421,7 @@ "links": { "Homepage": "https://metamorph.pro" }, - "marketcap_usd": 180164, + "marketcap_usd": 0, "name": "MetaMorph", "network": "eth", "shortcut": "METM", @@ -14433,7 +14441,7 @@ "Github": "https://github.com/syncfab", "Homepage": "https://syncfab.com/" }, - "marketcap_usd": 27962709, + "marketcap_usd": 11112282, "name": "SyncFab Smart Manufacturing Blockchain", "network": "eth", "shortcut": "MFG", @@ -14453,7 +14461,7 @@ "Github": "https://github.com/MainframeHQ", "Homepage": "https://mainframe.com" }, - "marketcap_usd": 92571247, + "marketcap_usd": 95539645, "name": "Mainframe Token", "network": "eth", "shortcut": "MFT", @@ -14491,7 +14499,7 @@ "links": { "Homepage": "https://mobilego.io" }, - "marketcap_usd": 1128407, + "marketcap_usd": 892801, "name": "MobileGo", "network": "eth", "shortcut": "MGO", @@ -14587,7 +14595,7 @@ "links": { "Homepage": "https://token.morpheuslabs.io" }, - "marketcap_usd": 17150512, + "marketcap_usd": 10583769, "name": "Morpheus Infrastructure Token", "network": "eth", "shortcut": "MITX", @@ -14601,26 +14609,6 @@ } ] }, - "erc20:eth:MKR": { - "address": "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2", - "links": { - "Github": "https://github.com/makerdao", - "Homepage": "https://makerdao.com" - }, - "marketcap_usd": 2641533334, - "name": "MakerDAO", - "network": "eth", - "shortcut": "MKR", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:MKT": { "address": "0x7939882b54fcf0bCAe6b53dEc39Ad6e806176442", "links": { @@ -14641,25 +14629,6 @@ } ] }, - "erc20:eth:MLN (new)": { - "address": "0xec67005c4E498Ec7f55E092bd1d35cbC47C91892", - "links": { - "Homepage": "https://melonport.com" - }, - "marketcap_usd": 149366107, - "name": "Melonport", - "network": "eth", - "shortcut": "MLN (new)", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:MM": { "address": "0x6B4c7A5e3f0B99FCD83e9c089BDDD6c7FCe5c611", "links": { @@ -14743,7 +14712,7 @@ "Github": "https://github.com/Goldmint", "Homepage": "https://goldmint.io" }, - "marketcap_usd": 427676, + "marketcap_usd": 469338, "name": "Goldmint MNT Prelaunch Token", "network": "eth", "shortcut": "MNTP", @@ -14936,7 +14905,7 @@ "Github": "https://github.com/mstable", "Homepage": "http://mstable.org" }, - "marketcap_usd": 13275260, + "marketcap_usd": 7750748, "name": "mStable Meta", "network": "eth", "shortcut": "MTA", @@ -14955,7 +14924,7 @@ "links": { "Homepage": "http://www.monetha.io" }, - "marketcap_usd": 13189939, + "marketcap_usd": 3562686, "name": "Monetha", "network": "eth", "shortcut": "MTH", @@ -14974,7 +14943,7 @@ "links": { "Homepage": "https://www.metalpay.com" }, - "marketcap_usd": 150717646, + "marketcap_usd": 132978179, "name": "Metal", "network": "eth", "shortcut": "MTL", @@ -14993,7 +14962,7 @@ "links": { "Homepage": "https://medicalchain.com" }, - "marketcap_usd": 1561899, + "marketcap_usd": 2053867, "name": "MedToken", "network": "eth", "shortcut": "MTN", @@ -15050,7 +15019,7 @@ "links": { "Homepage": "https://www.matryx.ai" }, - "marketcap_usd": 118824, + "marketcap_usd": 104299, "name": "Matryx", "network": "eth", "shortcut": "MTX", @@ -15127,7 +15096,7 @@ "links": { "Homepage": "http://mvlchain.io" }, - "marketcap_usd": 166092560, + "marketcap_usd": 244393776, "name": "Mass Vehicle Ledger Token", "network": "eth", "shortcut": "MVL", @@ -15147,7 +15116,7 @@ "Github": "https://github.com/Merculet", "Homepage": "https://www.merculet.io" }, - "marketcap_usd": 1673808, + "marketcap_usd": 1367938, "name": "Merculet", "network": "eth", "shortcut": "MVP", @@ -15185,7 +15154,7 @@ "links": { "Homepage": "https://mysterium.network/" }, - "marketcap_usd": 9565015, + "marketcap_usd": 7138959, "name": "Mysterium", "network": "eth", "shortcut": "MYST", @@ -15224,7 +15193,7 @@ "Github": "https://github.com/NANJ-COIN", "Homepage": "https://nanjcoin.com/" }, - "marketcap_usd": 782496, + "marketcap_usd": 4968286, "name": "NANJCOIN", "network": "eth", "shortcut": "NANJ", @@ -15321,7 +15290,7 @@ "links": { "Homepage": "https://niobiumcoin.io" }, - "marketcap_usd": 337092, + "marketcap_usd": 258384, "name": "Niobium Coin", "network": "eth", "shortcut": "NBC", @@ -15340,7 +15309,7 @@ "links": { "Homepage": "https://nucleus.vision" }, - "marketcap_usd": 14949793, + "marketcap_usd": 3880536, "name": "Nucleus Vision", "network": "eth", "shortcut": "NCASH", @@ -15380,7 +15349,7 @@ "Github": "https://github.com/polyswarm", "Homepage": "https://polyswarm.io" }, - "marketcap_usd": 40858180, + "marketcap_usd": 65697461, "name": "Nectar", "network": "eth", "shortcut": "NCT", @@ -15516,7 +15485,7 @@ "links": { "Homepage": "http://nexo.io" }, - "marketcap_usd": 1349884209, + "marketcap_usd": 1391545393, "name": "Nexo", "network": "eth", "shortcut": "NEXO", @@ -15575,7 +15544,7 @@ "Github": "https://github.com/nknorg", "Homepage": "https://nkn.org" }, - "marketcap_usd": 270476492, + "marketcap_usd": 188931285, "name": "NKN", "network": "eth", "shortcut": "NKN", @@ -15615,7 +15584,7 @@ "Github": "https://github.com/numerai", "Homepage": "https://numer.ai" }, - "marketcap_usd": 199395047, + "marketcap_usd": 185495978, "name": "Numerai", "network": "eth", "shortcut": "NMR", @@ -15713,7 +15682,7 @@ "links": { "Homepage": "https://napoleonx.ai" }, - "marketcap_usd": 4565235, + "marketcap_usd": 4561338, "name": "NaPoleonX", "network": "eth", "shortcut": "NPX", @@ -15733,7 +15702,7 @@ "Github": "https://github.com/pundix", "Homepage": "https://pundix.com" }, - "marketcap_usd": 292484948, + "marketcap_usd": 243108467, "name": "Pundi X Token", "network": "eth", "shortcut": "NPXS", @@ -15792,7 +15761,7 @@ "Github": "https://github.com/nucypher", "Homepage": "https://nucypher.com" }, - "marketcap_usd": 575605553, + "marketcap_usd": 328672132, "name": "NuCypher Network", "network": "eth", "shortcut": "NU", @@ -15811,7 +15780,7 @@ "links": { "Homepage": "https://nuggets.life/" }, - "marketcap_usd": 697063, + "marketcap_usd": 0, "name": "Nuggets Token", "network": "eth", "shortcut": "NUG", @@ -15965,7 +15934,7 @@ "links": { "Homepage": "https://www.openanx.org/en" }, - "marketcap_usd": 17455731, + "marketcap_usd": 9558667, "name": "OAX", "network": "eth", "shortcut": "OAX", @@ -16025,7 +15994,7 @@ "Github": "https://github.com/oceanprotocol", "Homepage": "https://oceanprotocol.com" }, - "marketcap_usd": 577717328, + "marketcap_usd": 395147271, "name": "Ocean Token", "network": "eth", "shortcut": "OCEAN", @@ -16044,7 +16013,7 @@ "links": { "Homepage": "http://www.ocnex.net" }, - "marketcap_usd": 2296521, + "marketcap_usd": 2008999, "name": "Odyssey", "network": "eth", "shortcut": "OCN", @@ -16064,7 +16033,7 @@ "Github": "https://github.com/octofi", "Homepage": "https://octo.fi" }, - "marketcap_usd": 4653341, + "marketcap_usd": 3189495, "name": "OctoFi", "network": "eth", "shortcut": "OCTO", @@ -16124,7 +16093,7 @@ "Github": "https://github.com/originprotocol", "Homepage": "https://www.originprotocol.com" }, - "marketcap_usd": 277365087, + "marketcap_usd": 235815344, "name": "OriginToken", "network": "eth", "shortcut": "OGN", @@ -16184,7 +16153,7 @@ "Github": "https://github.com/okex/okberc20token", "Homepage": "https://www.okex.com/" }, - "marketcap_usd": 1785845074, + "marketcap_usd": 1326672049, "name": "OKB", "network": "eth", "shortcut": "OKB", @@ -16243,7 +16212,7 @@ "Github": "https://github.com/Oneledger", "Homepage": "https://oneledger.io" }, - "marketcap_usd": 21263702, + "marketcap_usd": 0, "name": "OneLedger Token", "network": "eth", "shortcut": "OLT", @@ -16263,7 +16232,7 @@ "Github": "https://github.com/omisego", "Homepage": "https://omg.omise.co" }, - "marketcap_usd": 0, + "marketcap_usd": 804123169, "name": "OmiseGO", "network": "eth", "shortcut": "OMG", @@ -16341,7 +16310,7 @@ "Github": "https://github.com/onGsocial", "Homepage": "https://somee.social" }, - "marketcap_usd": 2353716, + "marketcap_usd": 1414313, "name": "SoMee.Social", "network": "eth", "shortcut": "ONG", @@ -16418,7 +16387,7 @@ "links": { "Homepage": "https://opus-foundation.org" }, - "marketcap_usd": 101267, + "marketcap_usd": 54988, "name": "Opus Foundation", "network": "eth", "shortcut": "OPT", @@ -16437,7 +16406,7 @@ "links": { "Homepage": "https://optitoken.io" }, - "marketcap_usd": 168441, + "marketcap_usd": 0, "name": "OptiToken", "network": "eth", "shortcut": "OPTI", @@ -16476,7 +16445,7 @@ "Github": "https://github.com/orbs-network", "Homepage": "https://orbs.com" }, - "marketcap_usd": 199628167, + "marketcap_usd": 255924523, "name": "Orbs", "network": "eth", "shortcut": "ORBS", @@ -16554,7 +16523,7 @@ "links": { "Homepage": "https://www.originsport.io" }, - "marketcap_usd": 1466232, + "marketcap_usd": 1399715, "name": "Origin Sport", "network": "eth", "shortcut": "ORS", @@ -16613,7 +16582,7 @@ "Github": "https://github.com/OpenSTFoundation", "Homepage": "https://simpletoken.org" }, - "marketcap_usd": 2907317, + "marketcap_usd": 1257589, "name": "Simple Token 'OST'", "network": "eth", "shortcut": "OST", @@ -16672,7 +16641,7 @@ "Github": "https://github.com/originprotocol", "Homepage": "https://ousd.com" }, - "marketcap_usd": 8985640, + "marketcap_usd": 141726972, "name": "Origin Dollar", "network": "eth", "shortcut": "OUSD", @@ -16692,7 +16661,7 @@ "Github": "https://github.com/owndata", "Homepage": "https://owndata.network" }, - "marketcap_usd": 593636, + "marketcap_usd": 291943, "name": "OWNDATA", "network": "eth", "shortcut": "OWN", @@ -16732,7 +16701,7 @@ "Github": "https://github.com/orchidtechnologies/orchid", "Homepage": "https://www.orchid.com" }, - "marketcap_usd": 279221227, + "marketcap_usd": 195981661, "name": "Orchid", "network": "eth", "shortcut": "OXT", @@ -16850,7 +16819,7 @@ "links": { "Homepage": "https://patron-influencers.com" }, - "marketcap_usd": 1650436, + "marketcap_usd": 2503059, "name": "Patron", "network": "eth", "shortcut": "PAT", @@ -16929,7 +16898,7 @@ "Github": "https://github.com/paxosglobal", "Homepage": "https://www.paxos.com/standard" }, - "marketcap_usd": 946560261, + "marketcap_usd": 946539127, "name": "Paxos Standard (PAX)", "network": "eth", "shortcut": "PAX", @@ -16949,7 +16918,7 @@ "Github": "https://github.com/paxosglobal/paxos-gold-contract", "Homepage": "https://www.paxos.com/paxgold" }, - "marketcap_usd": 323707624, + "marketcap_usd": 606745775, "name": "Paxos Gold", "network": "eth", "shortcut": "PAXG", @@ -16968,7 +16937,7 @@ "links": { "Homepage": "http://www.tenx.tech" }, - "marketcap_usd": 10915500, + "marketcap_usd": 8944099, "name": "TenX", "network": "eth", "shortcut": "PAY", @@ -17026,7 +16995,7 @@ "Github": "https://github.com/Peculium-Dev/", "Homepage": "https://peculium.io" }, - "marketcap_usd": 9897956, + "marketcap_usd": 68585099, "name": "Peculium", "network": "eth", "shortcut": "PCL", @@ -17221,7 +17190,7 @@ "links": { "Homepage": "https://www.phitoken.io" }, - "marketcap_usd": 793139, + "marketcap_usd": 644023, "name": "PHI Token", "network": "eth", "shortcut": "PHI", @@ -17240,7 +17209,7 @@ "links": { "Homepage": "https://pickle.finance/" }, - "marketcap_usd": 13552251, + "marketcap_usd": 8900970, "name": "Pickle Finance", "network": "eth", "shortcut": "PICKLE", @@ -17259,7 +17228,7 @@ "links": { "Homepage": "https://piplcoin.com" }, - "marketcap_usd": 258073, + "marketcap_usd": 165193, "name": "PIPL Coin", "network": "eth", "shortcut": "PIPL", @@ -17335,7 +17304,7 @@ "links": { "Homepage": "http://pkgtoken.io" }, - "marketcap_usd": 199363, + "marketcap_usd": 129895, "name": "PKG Token", "network": "eth", "shortcut": "PKG", @@ -17354,7 +17323,7 @@ "links": { "Homepage": "https://playkey.io" }, - "marketcap_usd": 439134, + "marketcap_usd": 203016, "name": "Playkey", "network": "eth", "shortcut": "PKT", @@ -17412,7 +17381,7 @@ "Github": "https://github.com/twentythirty/PillarToken", "Homepage": "https://www.pillarproject.io" }, - "marketcap_usd": 5094380, + "marketcap_usd": 3951260, "name": "Pillar Project", "network": "eth", "shortcut": "PLR", @@ -17451,7 +17420,7 @@ "links": { "Homepage": "https://plutus.it" }, - "marketcap_usd": 5082036, + "marketcap_usd": 17016123, "name": "Pluton", "network": "eth", "shortcut": "PLU", @@ -17470,7 +17439,7 @@ "links": { "Homepage": "https://pumapay.io" }, - "marketcap_usd": 4324729, + "marketcap_usd": 1787063, "name": "PumaPay", "network": "eth", "shortcut": "PMA", @@ -17509,7 +17478,7 @@ "Github": "https://github.com/kleros", "Homepage": "https://kleros.io" }, - "marketcap_usd": 65838524, + "marketcap_usd": 62954096, "name": "Pinakion", "network": "eth", "shortcut": "PNK", @@ -17528,7 +17497,7 @@ "links": { "Homepage": "https://po.et" }, - "marketcap_usd": 328923, + "marketcap_usd": 180473, "name": "Po.et Tokens", "network": "eth", "shortcut": "POE", @@ -17585,7 +17554,7 @@ "links": { "Homepage": "https://polymath.network" }, - "marketcap_usd": 486359316, + "marketcap_usd": 458983692, "name": "Polymath Network", "network": "eth", "shortcut": "POLY", @@ -17663,7 +17632,7 @@ "links": { "Homepage": "https://powerledger.io" }, - "marketcap_usd": 214638096, + "marketcap_usd": 288897148, "name": "PowerLedger", "network": "eth", "shortcut": "POWR", @@ -17682,7 +17651,7 @@ "links": { "Homepage": "https://www.paypie.com" }, - "marketcap_usd": 1233958, + "marketcap_usd": 1974724, "name": "PayPie", "network": "eth", "shortcut": "PPP", @@ -17702,7 +17671,7 @@ "Github": "https://github.com/Bitpopulous", "Homepage": "https://populous.co" }, - "marketcap_usd": 39314471, + "marketcap_usd": 20363678, "name": "Populous", "network": "eth", "shortcut": "PPT", @@ -17760,7 +17729,7 @@ "links": { "Homepage": "https://privatix.io" }, - "marketcap_usd": 63969, + "marketcap_usd": 115837, "name": "Privatix", "network": "eth", "shortcut": "PRIX", @@ -17819,7 +17788,7 @@ "Github": "https://github.com/propsproject", "Homepage": "https://propsproject.com" }, - "marketcap_usd": 2731384, + "marketcap_usd": 2190442, "name": "Props", "network": "eth", "shortcut": "PROPS", @@ -17916,7 +17885,7 @@ "links": { "Homepage": "https://primas.io" }, - "marketcap_usd": 1243074, + "marketcap_usd": 1160692, "name": "Primas", "network": "eth", "shortcut": "PST", @@ -17975,7 +17944,7 @@ "links": { "Homepage": "https://patientory.com" }, - "marketcap_usd": 872495, + "marketcap_usd": 470691, "name": "Patientory", "network": "eth", "shortcut": "PTOY", @@ -18094,7 +18063,7 @@ "Github": "https://github.com/playgame-global", "Homepage": "https://its.playgame.com" }, - "marketcap_usd": 277288, + "marketcap_usd": 617150, "name": "PlayGame", "network": "eth", "shortcut": "PXG", @@ -18171,7 +18140,7 @@ "links": { "Homepage": "https://liquid.plus" }, - "marketcap_usd": 20645750, + "marketcap_usd": 26689401, "name": "QASH", "network": "eth", "shortcut": "QASH", @@ -18229,7 +18198,7 @@ "links": { "Homepage": "https://quarkchain.io" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "network": "eth", "shortcut": "QKC", @@ -18249,7 +18218,7 @@ "Github": "https://github.com/quantnetwork", "Homepage": "https://www.quant.network/" }, - "marketcap_usd": 2285721236, + "marketcap_usd": 1791590480, "name": "Quant", "network": "eth", "shortcut": "QNT", @@ -18308,7 +18277,7 @@ "Github": "https://github.com/quantstamp", "Homepage": "https://quantstamp.com/" }, - "marketcap_usd": 31455239, + "marketcap_usd": 50445800, "name": "Quantstamp Token", "network": "eth", "shortcut": "QSP", @@ -18406,7 +18375,7 @@ "Github": "https://github.com/rokfin/eth-contracts", "Homepage": "https://www.raetoken.org" }, - "marketcap_usd": 10830447, + "marketcap_usd": 9218068, "name": "RAE Token", "network": "eth", "shortcut": "RAE", @@ -18426,7 +18395,7 @@ "Github": "https://github.com/reflexer-labs/", "Homepage": "https://reflexer.finance/" }, - "marketcap_usd": 81548824, + "marketcap_usd": 66860938, "name": "Rai Reflex Index", "network": "eth", "shortcut": "RAI", @@ -18465,7 +18434,7 @@ "links": { "Homepage": "http://token.dprating.com" }, - "marketcap_usd": 590669, + "marketcap_usd": 396386, "name": "DPRating", "network": "eth", "shortcut": "RATING", @@ -18485,7 +18454,7 @@ "Github": "https://github.com/rublixdev", "Homepage": "https://rublix.io/" }, - "marketcap_usd": 1189451, + "marketcap_usd": 1007242, "name": "Rublix", "network": "eth", "shortcut": "RBLX", @@ -18524,7 +18493,7 @@ "Github": "https://github.com/ripio/rcn-token", "Homepage": "https://ripiocredit.network" }, - "marketcap_usd": 5551456, + "marketcap_usd": 4634281, "name": "Ripio Credit Network", "network": "eth", "shortcut": "RCN", @@ -18538,26 +18507,6 @@ } ] }, - "erc20:eth:RDN": { - "address": "0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6", - "links": { - "Github": "https://github.com/raiden-network/raiden/", - "Homepage": "https://raiden.network" - }, - "marketcap_usd": 18098621, - "name": "Raiden Network", - "network": "eth", - "shortcut": "RDN", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:RDV": { "address": "0xd967d9F941CD316Ab238d3EE761F80b7cAec7819", "links": { @@ -18641,7 +18590,7 @@ "Github": "https://github.com/red", "Homepage": "https://ico.red-lang.org" }, - "marketcap_usd": 950058, + "marketcap_usd": 614338, "name": "Red Community Token", "network": "eth", "shortcut": "RED", @@ -18681,7 +18630,7 @@ "Github": "http://github.com/reef-defi", "Homepage": "http://reef.finance" }, - "marketcap_usd": 340432061, + "marketcap_usd": 210968242, "name": "Reef Finance", "network": "eth", "shortcut": "REEF", @@ -18719,7 +18668,7 @@ "links": { "Homepage": "https://remme.io" }, - "marketcap_usd": 1057181, + "marketcap_usd": 447620, "name": "Remme", "network": "eth", "shortcut": "REM", @@ -18759,7 +18708,7 @@ "Github": "https://github.com/renproject", "Homepage": "https://renproject.io/" }, - "marketcap_usd": 624732144, + "marketcap_usd": 460980088, "name": "Republic Token", "network": "eth", "shortcut": "REN", @@ -18773,25 +18722,6 @@ } ] }, - "erc20:eth:REP": { - "address": "0x1985365e9f78359a9B6AD760e32412f4a445E862", - "links": { - "Homepage": "https://augur.net" - }, - "marketcap_usd": 209636343, - "name": "Augur", - "network": "eth", - "shortcut": "REP", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:REPv2": { "address": "0x221657776846890989a759BA2973e427DfF5C9bB", "links": { @@ -18816,7 +18746,7 @@ "links": { "Homepage": "https://request.network" }, - "marketcap_usd": 386865865, + "marketcap_usd": 266594085, "name": "Request Network", "network": "eth", "shortcut": "REQ", @@ -18836,7 +18766,7 @@ "Github": "https://github.com/Revain", "Homepage": "https://revain.org" }, - "marketcap_usd": 867997272, + "marketcap_usd": 493760966, "name": "Revain", "network": "eth", "shortcut": "REV", @@ -18875,7 +18805,7 @@ "links": { "Homepage": "https://refereum.com" }, - "marketcap_usd": 69903659, + "marketcap_usd": 63223097, "name": "Refereum", "network": "eth", "shortcut": "RFR", @@ -18967,25 +18897,6 @@ } ] }, - "erc20:eth:RLC": { - "address": "0x607F4C5BB672230e8672085532f7e901544a7375", - "links": { - "Homepage": "http://iex.ec/" - }, - "marketcap_usd": 242109147, - "name": "IEx.ec", - "network": "eth", - "shortcut": "RLC", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:RLT": { "address": "0xcCeD5B8288086BE8c38E23567e684C3740be4D48", "links": { @@ -19088,7 +18999,7 @@ "links": { "Homepage": "https://www.oneroot.io/en" }, - "marketcap_usd": 624050, + "marketcap_usd": 698568, "name": "OneRoot Network", "network": "eth", "shortcut": "RNT", @@ -19146,7 +19057,7 @@ "links": { "Homepage": "https://icerockmining.io" }, - "marketcap_usd": 174122, + "marketcap_usd": 33616, "name": "ICE ROCK MINING", "network": "eth", "shortcut": "ROCK2", @@ -19203,7 +19114,7 @@ "links": { "Homepage": "https://roobee.io/" }, - "marketcap_usd": 10811859, + "marketcap_usd": 9053524, "name": "ROOBEE", "network": "eth", "shortcut": "ROOBEE", @@ -19256,6 +19167,26 @@ } ] }, + "erc20:eth:RSR": { + "address": "0x320623b8E4fF03373931769A31Fc52A4E78B5d70", + "links": { + "Github": "https://github.com/reserve-protocol/rsr-mainnet", + "Homepage": "https://reserve.org" + }, + "marketcap_usd": 260058132, + "name": "Reserve Rights", + "network": "eth", + "shortcut": "RSR", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:RTB": { "address": "0xEC491c1088Eae992B7A214efB0a266AD0927A72A", "links": { @@ -19300,7 +19231,7 @@ "links": { "Homepage": "https://www.rotharium.io" }, - "marketcap_usd": 8330694, + "marketcap_usd": 4143524, "name": "Rotharium", "network": "eth", "shortcut": "RTH", @@ -19339,7 +19270,7 @@ "links": { "Homepage": "http://ruffchain.com" }, - "marketcap_usd": 2446131, + "marketcap_usd": 2409512, "name": "Ruff", "network": "eth", "shortcut": "RUFF", @@ -19397,7 +19328,7 @@ "links": { "Homepage": "https://rivetzintl.com" }, - "marketcap_usd": 256667, + "marketcap_usd": 188377, "name": "Rivetz", "network": "eth", "shortcut": "RVT", @@ -19513,7 +19444,7 @@ "links": { "Homepage": "https://saltlending.com" }, - "marketcap_usd": 10453328, + "marketcap_usd": 6421765, "name": "Salt Lending Token", "network": "eth", "shortcut": "SALT", @@ -19532,7 +19463,7 @@ "links": { "Homepage": "https://santiment.net" }, - "marketcap_usd": 23093314, + "marketcap_usd": 15706905, "name": "Santiment", "network": "eth", "shortcut": "SAN", @@ -19570,7 +19501,7 @@ "links": { "Homepage": "https://ico.nexus.social" }, - "marketcap_usd": 63331, + "marketcap_usd": 53369, "name": "SocialCoin", "network": "eth", "shortcut": "SCL", @@ -19647,7 +19578,7 @@ "links": { "Homepage": "https://www.sentinel-chain.org" }, - "marketcap_usd": 224940, + "marketcap_usd": 141076, "name": "Sentinel Chain", "network": "eth", "shortcut": "SENC", @@ -19738,6 +19669,26 @@ } ] }, + "erc20:eth:SEV": { + "address": "0xaf50F8bEc1DbEC013B7025dB444Da019c2f5d488", + "links": { + "Github": "https://github.com/SeveraDAO/Sev-Token", + "Homepage": "https://severadao.ai" + }, + "marketcap_usd": 0, + "name": "SeveraDAO", + "network": "eth", + "shortcut": "SEV", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:SEXY": { "address": "0x98F5e9b7F0e33956C0443E81bF7deB8B5b1ed545", "links": { @@ -19839,7 +19790,7 @@ "links": { "Homepage": "https://shibatoken.com" }, - "marketcap_usd": 20545789697, + "marketcap_usd": 15351337749, "name": "SHIBA INU", "network": "eth", "shortcut": "SHIB", @@ -19858,7 +19809,7 @@ "links": { "Homepage": "https://www.shipchain.io" }, - "marketcap_usd": 882872, + "marketcap_usd": 1130487, "name": "ShipChain", "network": "eth", "shortcut": "SHIP", @@ -20013,7 +19964,7 @@ "links": { "Homepage": "https://www.skb-coin.jp/en" }, - "marketcap_usd": 698392, + "marketcap_usd": 52453, "name": "Sakura Bloom", "network": "eth", "shortcut": "SKB", @@ -20052,7 +20003,7 @@ "Github": "https://github.com/Steamtradenet/smart-contract", "Homepage": "https://skincoin.org" }, - "marketcap_usd": 217396, + "marketcap_usd": 158116, "name": "SKIN", "network": "eth", "shortcut": "SKIN", @@ -20148,7 +20099,7 @@ "links": { "Homepage": "https://youengine.io" }, - "marketcap_usd": 100501963, + "marketcap_usd": 118155598, "name": "Smooth Love Potion", "network": "eth", "shortcut": "SLP", @@ -20225,7 +20176,7 @@ "links": { "Homepage": "https://suncontract.org" }, - "marketcap_usd": 3731047, + "marketcap_usd": 3455530, "name": "SunContract", "network": "eth", "shortcut": "SNC", @@ -20361,7 +20312,7 @@ "Github": "https://github.com/status-im", "Homepage": "https://status.im" }, - "marketcap_usd": 257208781, + "marketcap_usd": 263276393, "name": "Status Network Token", "network": "eth", "shortcut": "SNT", @@ -20400,7 +20351,7 @@ "Github": "https://github.com/havven/havven", "Homepage": "https://synthetix.io" }, - "marketcap_usd": 669775637, + "marketcap_usd": 672289697, "name": "Synthetix Network Token", "network": "eth", "shortcut": "SNX", @@ -20438,7 +20389,7 @@ "links": { "Homepage": "https://www.allsportschain.com" }, - "marketcap_usd": 2514229, + "marketcap_usd": 3643795, "name": "All Sports", "network": "eth", "shortcut": "SOC", @@ -20496,7 +20447,7 @@ "Github": "https://github.com/cryptosoulgame", "Homepage": "https://cryptosoul.io/" }, - "marketcap_usd": 1177959, + "marketcap_usd": 438773, "name": "CryptoSoul", "network": "eth", "shortcut": "SOUL", @@ -20632,7 +20583,7 @@ "links": { "Homepage": "https://spindle.zone" }, - "marketcap_usd": 169948, + "marketcap_usd": 497859, "name": "SPINDLE", "network": "eth", "shortcut": "SPD", @@ -20729,7 +20680,7 @@ "Github": "https://github.com/sirin-labs/crowdsale-smart-contract", "Homepage": "https://sirinlabs.com" }, - "marketcap_usd": 2688356, + "marketcap_usd": 1680626, "name": "Sirin Labs", "network": "eth", "shortcut": "SRN", @@ -20787,7 +20738,7 @@ "links": { "Homepage": "https://smartshare.vip/#" }, - "marketcap_usd": 329890, + "marketcap_usd": 278497, "name": "Smartshare", "network": "eth", "shortcut": "SSP", @@ -20825,7 +20776,7 @@ "links": { "Homepage": "https://coinstarter.com" }, - "marketcap_usd": 49519, + "marketcap_usd": 47504, "name": "Starter Coin", "network": "eth", "shortcut": "STAC", @@ -20863,7 +20814,7 @@ "links": { "Homepage": "http://starbase.co" }, - "marketcap_usd": 816388, + "marketcap_usd": 625730, "name": "Star Token", "network": "eth", "shortcut": "STAR", @@ -21019,7 +20970,7 @@ "Github": "https://github.com/Storj", "Homepage": "https://storj.io" }, - "marketcap_usd": 702762692, + "marketcap_usd": 529652219, "name": "STORJ", "network": "eth", "shortcut": "STORJ", @@ -21097,7 +21048,7 @@ "links": { "Homepage": "https://staker.network" }, - "marketcap_usd": 2539, + "marketcap_usd": 2438, "name": "Staker", "network": "eth", "shortcut": "STR", @@ -21156,7 +21107,7 @@ "Github": "https://github.com/stx-technologies/stox-token", "Homepage": "https://www.stox.com" }, - "marketcap_usd": 0, + "marketcap_usd": 452229, "name": "StoxToken", "network": "eth", "shortcut": "STX", @@ -21176,7 +21127,7 @@ "Github": "https://github.com/SubstratumNetwork", "Homepage": "https://substratum.net" }, - "marketcap_usd": 1060062, + "marketcap_usd": 857059, "name": "Substratum", "network": "eth", "shortcut": "SUB", @@ -21215,7 +21166,7 @@ "Github": "https://github.com/sushiswap", "Homepage": "https://sushiswapclassic.org/" }, - "marketcap_usd": 973142849, + "marketcap_usd": 535858382, "name": "SushiToken", "network": "eth", "shortcut": "SUSHI", @@ -21274,7 +21225,7 @@ "Github": "https://github.com/swashapp/", "Homepage": "https://swashapp.io/" }, - "marketcap_usd": 10320808, + "marketcap_usd": 7649197, "name": "Swash Token", "network": "eth", "shortcut": "SWASH", @@ -21293,7 +21244,7 @@ "links": { "Homepage": "http://www.swftcoin.com" }, - "marketcap_usd": 5296780, + "marketcap_usd": 10424842, "name": "SwftCoin", "network": "eth", "shortcut": "SWFTC", @@ -21332,7 +21283,7 @@ "links": { "Homepage": "http://swarm.city" }, - "marketcap_usd": 236547, + "marketcap_usd": 298307, "name": "Swarm City Token", "network": "eth", "shortcut": "SWT", @@ -21390,7 +21341,7 @@ "links": { "Homepage": "http://www.spectre.ai" }, - "marketcap_usd": 1712212, + "marketcap_usd": 1150795, "name": "Spectre.ai U-Token", "network": "eth", "shortcut": "SXUT", @@ -21423,6 +21374,25 @@ } ] }, + "erc20:eth:SYS": { + "address": "0x46EaF75e6d391708b7F1a0D56875D90844119521", + "links": { + "Homepage": "https://syscoin.org" + }, + "marketcap_usd": 0, + "name": "Syscoin", + "network": "eth", + "shortcut": "SYS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:SYSX": { "address": "0x3A0D746B3EA1d8ccDf19aD915913BD68391133Ca", "links": { @@ -21486,7 +21456,7 @@ "links": { "Homepage": "https://taklimakan.io" }, - "marketcap_usd": 173911, + "marketcap_usd": 86817, "name": "Taklimakan Network", "network": "eth", "shortcut": "TAN", @@ -21644,7 +21614,7 @@ "links": { "Homepage": "https://tokenbox.io" }, - "marketcap_usd": 222471, + "marketcap_usd": 154105, "name": "Tokenbox", "network": "eth", "shortcut": "TBX", @@ -21703,7 +21673,7 @@ "links": { "Homepage": "https://www.thorecash.com" }, - "marketcap_usd": 13350, + "marketcap_usd": 13288, "name": "Thore Cash", "network": "eth", "shortcut": "TCH", @@ -21837,7 +21807,7 @@ "links": { "Homepage": "https://www.tokenomy.com" }, - "marketcap_usd": 11099553, + "marketcap_usd": 9148623, "name": "Tokenomy", "network": "eth", "shortcut": "TEN", @@ -21896,7 +21866,7 @@ "Github": "https://github.com/TrueFlip", "Homepage": "https://trueflip.io" }, - "marketcap_usd": 8081900, + "marketcap_usd": 5396506, "name": "TrueFlip", "network": "eth", "shortcut": "TFL", @@ -21915,7 +21885,7 @@ "links": { "Homepage": "https://ico.truegame.io" }, - "marketcap_usd": 74420, + "marketcap_usd": 82088, "name": "Truegame", "network": "eth", "shortcut": "TGAME", @@ -22070,7 +22040,7 @@ "links": { "Homepage": "https://chronobase.eu/" }, - "marketcap_usd": 413320, + "marketcap_usd": 341566, "name": "ChronoBase", "network": "eth", "shortcut": "TIK", @@ -22127,7 +22097,7 @@ "links": { "Homepage": "https://www.blocktix.io" }, - "marketcap_usd": 99713, + "marketcap_usd": 268083, "name": "Blocktix", "network": "eth", "shortcut": "TIX", @@ -22184,7 +22154,7 @@ "links": { "Homepage": "https://etherscan.io/token/TokenCard" }, - "marketcap_usd": 8791365, + "marketcap_usd": 6796528, "name": "TokenCard", "network": "eth", "shortcut": "TKN", @@ -22204,7 +22174,7 @@ "Github": "https://github.com/Tokpie/tokpie-contract", "Homepage": "https://tokpie.io/" }, - "marketcap_usd": 2303082, + "marketcap_usd": 1699496, "name": "TOKPIE", "network": "eth", "shortcut": "TKP", @@ -22301,7 +22271,7 @@ "links": { "Homepage": "https://transcodium.com" }, - "marketcap_usd": 270382, + "marketcap_usd": 152171, "name": "Transcodium", "network": "eth", "shortcut": "TNS", @@ -22379,7 +22349,7 @@ "links": { "Homepage": "https://origintrail.io" }, - "marketcap_usd": 406647585, + "marketcap_usd": 270587047, "name": "OriginTrail", "network": "eth", "shortcut": "TRAC", @@ -22475,7 +22445,7 @@ "Github": "https://github.com/WeTrustPlatform", "Homepage": "https://www.wetrust.io" }, - "marketcap_usd": 1072780, + "marketcap_usd": 616019, "name": "WeTrust", "network": "eth", "shortcut": "TRST", @@ -22592,7 +22562,7 @@ "Github": "https://github.com/trusttoken", "Homepage": "https://www.trusttoken.com" }, - "marketcap_usd": 1314260651, + "marketcap_usd": 1350841107, "name": "TrueUSD", "network": "eth", "shortcut": "TUSD", @@ -22689,7 +22659,7 @@ "Github": "https://github.com/ubex-ai", "Homepage": "https://www.ubex.com/" }, - "marketcap_usd": 834311, + "marketcap_usd": 798055, "name": "UBEX Token", "network": "eth", "shortcut": "UBEX", @@ -22708,7 +22678,7 @@ "links": { "Homepage": "https://unibright.io" }, - "marketcap_usd": 264891578, + "marketcap_usd": 219113013, "name": "Unibright", "network": "eth", "shortcut": "UBT", @@ -22766,7 +22736,7 @@ "links": { "Homepage": "https://uchain.world" }, - "marketcap_usd": 24408, + "marketcap_usd": 13582, "name": "UChain", "network": "eth", "shortcut": "UCN", @@ -22785,7 +22755,7 @@ "links": { "Homepage": "https://www.upfiring.com" }, - "marketcap_usd": 1819318, + "marketcap_usd": 1092016, "name": "Upfiring", "network": "eth", "shortcut": "UFR", @@ -22825,7 +22795,7 @@ "Github": "https://github.com/umbrella-network", "Homepage": "https://umb.network/" }, - "marketcap_usd": 22577301, + "marketcap_usd": 9822192, "name": "Umbrella", "network": "eth", "shortcut": "UMB", @@ -22844,7 +22814,7 @@ "links": { "Homepage": "https://uniswap.org/" }, - "marketcap_usd": 10665482002, + "marketcap_usd": 7974869944, "name": "Uniswap", "network": "eth", "shortcut": "UNI", @@ -22863,7 +22833,7 @@ "links": { "Homepage": "https://uptoken.org" }, - "marketcap_usd": 271147, + "marketcap_usd": 209693, "name": "UpToken", "network": "eth", "shortcut": "UP", @@ -22882,7 +22852,7 @@ "links": { "Homepage": "https://sentinelprotocol.io" }, - "marketcap_usd": 70394801, + "marketcap_usd": 65723092, "name": "Sentinel Protocol", "network": "eth", "shortcut": "UPP", @@ -22981,7 +22951,7 @@ "Github": "https://github.com/centrehq/centre-tokens", "Homepage": "https://www.centre.io" }, - "marketcap_usd": 42415979569, + "marketcap_usd": 51902050847, "name": "USD//Coin", "network": "eth", "shortcut": "USDC", @@ -23000,7 +22970,7 @@ "links": { "Homepage": "https://stably.io" }, - "marketcap_usd": 284526, + "marketcap_usd": 481233, "name": "StableUSD", "network": "eth", "shortcut": "USDS", @@ -23019,7 +22989,7 @@ "links": { "Homepage": "https://tether.to" }, - "marketcap_usd": 78076571697, + "marketcap_usd": 81569830177, "name": "USD Tether (erc20)", "network": "eth", "shortcut": "USDT", @@ -23059,7 +23029,7 @@ "Github": "https://github.com/utrustdev/", "Homepage": "https://utrust.com" }, - "marketcap_usd": 147747045, + "marketcap_usd": 127724730, "name": "Utrust", "network": "eth", "shortcut": "UTK", @@ -23117,7 +23087,7 @@ "links": { "Homepage": "https://u.network/" }, - "marketcap_usd": 1059246, + "marketcap_usd": 640008, "name": "U Networks", "network": "eth", "shortcut": "UUU", @@ -23137,7 +23107,7 @@ "Github": "https://github.com/smartvalor/ValorToken", "Homepage": "https://smartvalor.com" }, - "marketcap_usd": 35480191, + "marketcap_usd": 11256128, "name": "ValorToken", "network": "eth", "shortcut": "VALOR", @@ -23177,7 +23147,7 @@ "Github": "https://github.com/VeriDocGlobal", "Homepage": "https://www.veridocglobal.com/" }, - "marketcap_usd": 4845598, + "marketcap_usd": 3930760, "name": "VeriDocGlobal", "network": "eth", "shortcut": "VDG", @@ -23217,7 +23187,7 @@ "Github": "https://github.com/blockv", "Homepage": "https://blockv.io" }, - "marketcap_usd": 33905419, + "marketcap_usd": 15003926, "name": "BLOCKv", "network": "eth", "shortcut": "VEE", @@ -23237,7 +23207,7 @@ "Github": "https://github.com/vegaprotocol", "Homepage": "https://vega.xyz" }, - "marketcap_usd": 88573378, + "marketcap_usd": 70086808, "name": "Vega", "network": "eth", "shortcut": "VEGA", @@ -23294,7 +23264,7 @@ "links": { "Homepage": "https://veritas.veritaseum.com" }, - "marketcap_usd": 339743833, + "marketcap_usd": 151881716, "name": "Veritaseum", "network": "eth", "shortcut": "VERI", @@ -23313,7 +23283,7 @@ "links": { "Homepage": "https://www.viberate.com" }, - "marketcap_usd": 8765221, + "marketcap_usd": 6182475, "name": "Viberate", "network": "eth", "shortcut": "VIB", @@ -23332,7 +23302,7 @@ "links": { "Homepage": "https://www.vibehub.io" }, - "marketcap_usd": 8923049, + "marketcap_usd": 3813392, "name": "VIBE Coin", "network": "eth", "shortcut": "VIBE", @@ -23372,7 +23342,7 @@ "Github": "https://github.com/videocoin", "Homepage": "https://www.videocoin.io" }, - "marketcap_usd": 59023362, + "marketcap_usd": 25122648, "name": "VideoCoin", "network": "eth", "shortcut": "VID", @@ -23431,7 +23401,7 @@ "links": { "Homepage": "https://ico.vikky.io" }, - "marketcap_usd": 684674, + "marketcap_usd": 650434, "name": "VikkyToken", "network": "eth", "shortcut": "VIKKY", @@ -23510,7 +23480,7 @@ "Github": "https://github.com/vetri-global/", "Homepage": "https://vetri.global/" }, - "marketcap_usd": 1673073, + "marketcap_usd": 5185539, "name": "VETRI", "network": "eth", "shortcut": "VLD", @@ -23587,7 +23557,7 @@ "links": { "Homepage": "https://vnx.io/" }, - "marketcap_usd": 896806, + "marketcap_usd": 2031600, "name": "VNX Exchange", "network": "eth", "shortcut": "VNXLU", @@ -23761,7 +23731,7 @@ "links": { "Homepage": "https://wab.network" }, - "marketcap_usd": 84732, + "marketcap_usd": 81356, "name": "WABnetwork", "network": "eth", "shortcut": "WAB", @@ -23780,7 +23750,7 @@ "links": { "Homepage": "https://taelpay.com" }, - "marketcap_usd": 20274608, + "marketcap_usd": 12338009, "name": "Tael", "network": "eth", "shortcut": "WABI", @@ -23899,7 +23869,7 @@ "Github": "https://github.com/WrappedBTC", "Homepage": "https://wbtc.network" }, - "marketcap_usd": 13004918822, + "marketcap_usd": 13121816934, "name": "Wrapped Bitcoin", "network": "eth", "shortcut": "WBTC", @@ -24094,7 +24064,7 @@ "links": { "Homepage": "https://wings.ai" }, - "marketcap_usd": 1740858, + "marketcap_usd": 1820189, "name": "WINGS", "network": "eth", "shortcut": "WINGS", @@ -24127,6 +24097,46 @@ } ] }, + "erc20:eth:WLKR": { + "address": "0xD64DeEA5F24934E3A1aa752912aEe8ffD8300C3F", + "links": { + "Github": "https://github.com/wlkrfinancial", + "Homepage": "https://wlkr.finance/ " + }, + "marketcap_usd": 0, + "name": "WLKR Innovation Index", + "network": "eth", + "shortcut": "WLKR", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, + "erc20:eth:WLKRR": { + "address": "0xC90206AB21bdbF5e92AfF4E6B5F097B65b0eCc06", + "links": { + "Github": "https://github.com/wlkrfinancial", + "Homepage": "https://wlkr.finance" + }, + "marketcap_usd": 0, + "name": "Walker", + "network": "eth", + "shortcut": "WLKRR", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:eth:WMA": { "address": "0x685ED390B16Ac9Df9Ab9707294a42a107cFB62Af", "links": { @@ -24210,7 +24220,7 @@ "links": { "Homepage": "https://wepower.network" }, - "marketcap_usd": 2375359, + "marketcap_usd": 1631975, "name": "WePower Token", "network": "eth", "shortcut": "WPR", @@ -24229,7 +24239,7 @@ "links": { "Homepage": "https://worldcore.eu" }, - "marketcap_usd": 83987, + "marketcap_usd": 85261, "name": "Worldcore", "network": "eth", "shortcut": "WRC", @@ -24348,7 +24358,7 @@ "links": { "Homepage": "https://x8currency.com" }, - "marketcap_usd": 1275189, + "marketcap_usd": 1139878, "name": "X8X", "network": "eth", "shortcut": "X8X", @@ -24367,7 +24377,7 @@ "links": { "Homepage": "https://www.antiample.org/" }, - "marketcap_usd": 1895265, + "marketcap_usd": 1557503, "name": "Antiample", "network": "eth", "shortcut": "XAMP", @@ -24386,7 +24396,7 @@ "links": { "Homepage": "http://www.xaurum.org" }, - "marketcap_usd": 2129471, + "marketcap_usd": 2794419, "name": "Xaurum", "network": "eth", "shortcut": "XAUR", @@ -24425,7 +24435,7 @@ "Github": "https://github.com/blitzpredict", "Homepage": "https://www.blitzpredict.io" }, - "marketcap_usd": 698567, + "marketcap_usd": 510985, "name": "BlitzPredict", "network": "eth", "shortcut": "XBP", @@ -24464,7 +24474,7 @@ "links": { "Homepage": "https://www.swisscryptotokens.ch/" }, - "marketcap_usd": 2164319, + "marketcap_usd": 2161695, "name": "CryptoFranc", "network": "eth", "shortcut": "XCHF", @@ -24696,7 +24706,7 @@ "links": { "Homepage": "https://xio.network/" }, - "marketcap_usd": 5317827, + "marketcap_usd": 3178836, "name": "XIO Network", "network": "eth", "shortcut": "XIO", @@ -24755,7 +24765,7 @@ "Github": "https://github.com/XMaxPlatform", "Homepage": "https://www.xmx.com" }, - "marketcap_usd": 1533695, + "marketcap_usd": 966633, "name": "XMax", "network": "eth", "shortcut": "XMX", @@ -24775,7 +24785,7 @@ "Github": "https://github.com/InkProtocol/", "Homepage": "https://paywithink.com" }, - "marketcap_usd": 391524, + "marketcap_usd": 393512, "name": "Ink Protocol", "network": "eth", "shortcut": "XNK", @@ -24832,7 +24842,7 @@ "links": { "Homepage": "http://www.xov.io" }, - "marketcap_usd": 43932, + "marketcap_usd": 38818, "name": "XOVBank", "network": "eth", "shortcut": "XOV", @@ -24851,7 +24861,7 @@ "links": { "Homepage": "https://xpa.io" }, - "marketcap_usd": 11553, + "marketcap_usd": 69005, "name": "XPA", "network": "eth", "shortcut": "XPA", @@ -24871,7 +24881,7 @@ "Github": "https://github.com/Bit-Nation/", "Homepage": "https://bitnation.co" }, - "marketcap_usd": 30400, + "marketcap_usd": 0, "name": "Pangea Arbitration Token", "network": "eth", "shortcut": "XPAT", @@ -24911,7 +24921,7 @@ "Github": "https://github.com/ProtonProtocol", "Homepage": "https://www.protonchain.com/" }, - "marketcap_usd": 157637676, + "marketcap_usd": 139013722, "name": "Proton", "network": "eth", "shortcut": "XPR", @@ -24930,7 +24940,7 @@ "links": { "Homepage": "https://cryptobuyer.io" }, - "marketcap_usd": 49206, + "marketcap_usd": 26604, "name": "Cryptobuyer Token", "network": "eth", "shortcut": "XPT", @@ -24988,7 +24998,7 @@ "Github": "https://github.com/Xfers/StraitsX-tokens", "Homepage": "https://xfers.com/sg/stablecoin" }, - "marketcap_usd": 198518435, + "marketcap_usd": 163441614, "name": "Singapore-Dollar Backed Stablecoin", "network": "eth", "shortcut": "XSGD", @@ -25007,7 +25017,7 @@ "links": { "Homepage": "https://xyo.network" }, - "marketcap_usd": 475956818, + "marketcap_usd": 265550405, "name": "XYO", "network": "eth", "shortcut": "XYO", @@ -25066,7 +25076,7 @@ "links": { "Homepage": "http://www.yeefoundation.com" }, - "marketcap_usd": 2693107, + "marketcap_usd": 671181, "name": "Yee Token", "network": "eth", "shortcut": "YEE", @@ -25086,7 +25096,7 @@ "Github": "https://github.com/iearn-finance", "Homepage": "https://yearn.finance/" }, - "marketcap_usd": 1139083466, + "marketcap_usd": 841765380, "name": "yearn.finance", "network": "eth", "shortcut": "YFI", @@ -25106,7 +25116,7 @@ "Github": "https://github.com/yfii/vault", "Homepage": "https://dfi.money/" }, - "marketcap_usd": 112110871, + "marketcap_usd": 90907718, "name": "YFII.finance", "network": "eth", "shortcut": "YFII", @@ -25146,7 +25156,7 @@ "Github": "https://github.com/YOUengine", "Homepage": "https://youengine.io" }, - "marketcap_usd": 1752828565, + "marketcap_usd": 614008199, "name": "yOUcash", "network": "eth", "shortcut": "YOUC", @@ -25186,7 +25196,7 @@ "Github": "https://github.com/zapproject", "Homepage": "https://zap.store" }, - "marketcap_usd": 4798804, + "marketcap_usd": 1316743, "name": "ZAP", "network": "eth", "shortcut": "ZAP", @@ -25205,7 +25215,7 @@ "links": { "Homepage": "https://0chain.net" }, - "marketcap_usd": 22666691, + "marketcap_usd": 24915664, "name": "0chain", "network": "eth", "shortcut": "ZCN", @@ -25243,7 +25253,7 @@ "links": { "Homepage": "https://zsc.io/" }, - "marketcap_usd": 252634, + "marketcap_usd": 175499, "name": "Zeusshield", "network": "eth", "shortcut": "ZCS", @@ -25302,7 +25312,7 @@ "Github": "https://github.com/ZEUS-coin", "Homepage": "https://zeusfundme.com/" }, - "marketcap_usd": 69802, + "marketcap_usd": 33510, "name": "ZeusNetwork", "network": "eth", "shortcut": "ZEUS", @@ -25321,7 +25331,7 @@ "links": { "Homepage": "https://zinc.work" }, - "marketcap_usd": 32496, + "marketcap_usd": 26290, "name": "ZINC", "network": "eth", "shortcut": "ZINC", @@ -25398,7 +25408,7 @@ "links": { "Homepage": "https://zla.io" }, - "marketcap_usd": 212995, + "marketcap_usd": 142467, "name": "Zilla", "network": "eth", "shortcut": "ZLA", @@ -25456,7 +25466,7 @@ "links": { "Homepage": "https://zper.io" }, - "marketcap_usd": 291378, + "marketcap_usd": 53365, "name": "ZPER", "network": "eth", "shortcut": "ZPR", @@ -25470,26 +25480,6 @@ } ] }, - "erc20:eth:ZRX": { - "address": "0xE41d2489571d322189246DaFA5ebDe1F4699F498", - "links": { - "Github": "https://github.com/0xProject", - "Homepage": "https://0xproject.com" - }, - "marketcap_usd": 738745337, - "name": "0x Project", - "network": "eth", - "shortcut": "ZRX", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "erc20", - "wallet": [ - { - "name": "Trezor Suite", - "url": "https://suite.trezor.io" - } - ] - }, "erc20:eth:ZST": { "address": "0xe386B139Ed3715Ca4B18Fd52671bDcea1cdFE4b1", "links": { @@ -25514,7 +25504,7 @@ "links": { "Homepage": "https://0xcert.org" }, - "marketcap_usd": 747725, + "marketcap_usd": 316094, "name": "0xcert Protocol Token", "network": "eth", "shortcut": "ZXC", @@ -26592,7 +26582,7 @@ "Github": "https://github.com/eosdac", "Homepage": "https://eosdac.io/" }, - "marketcap_usd": 1210510, + "marketcap_usd": 705091, "name": "eosDAC", "network": "eth", "shortcut": "eosDAC", @@ -32386,6 +32376,96 @@ } ] }, + "erc20:rin:BHNT": { + "address": "0xe27826eE778B6F78a49a686dA7D64f6E7b084a4f", + "links": { + "Github": "https://github.com/berlin-hack-and-tell", + "Homepage": "http://berlin.hackandtell.org" + }, + "marketcap_usd": 0, + "name": "Berlin Hack&Tell winner token", + "network": "rin", + "shortcut": "BHNT", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "erc20:rin:CTGA": { + "address": "0x8B65d4B7ee3FFFA986C577F0F4b70a21BaE3dD54", + "links": { + "Homepage": "https://www.ctgcoin.org" + }, + "marketcap_usd": 0, + "name": "Convenient To Go", + "network": "rin", + "shortcut": "CTGA", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "erc20:rin:WALL": { + "address": "0x0A057a87CE9C56D7e336B417c79cf30E8d27860B", + "links": { + "Github": "https://github.com/walleth", + "Homepage": "https://walleth.org" + }, + "marketcap_usd": 0, + "name": "WALLETH Community-Token", + "network": "rin", + "shortcut": "WALL", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "erc20:rop:dqr30": { + "address": "0xa1bAccA0e12D4091Ec1f92e7CaE3394CC9854D3D", + "links": { + "Homepage": "https://dqr-group.com/" + }, + "marketcap_usd": 0, + "name": "DQR", + "network": "rop", + "shortcut": "dqr30", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, "erc20:rsk:BPro": { "address": "0x440CD83C160De5C96Ddb20246815eA44C7aBBCa8", "links": { @@ -32576,6 +32656,75 @@ } ] }, + "erc20:ubq:GEO": { + "address": "0x500684CE0D4f04aBeDff3e54fCF8acC5E6CFc4bD", + "links": { + "Homepage": "https://geo.money" + }, + "marketcap_usd": 0, + "name": "GeoCoin", + "network": "ubq", + "shortcut": "GEO", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "erc20:ubq:GRANS": { + "address": "0x0826180A4c981d5095Cb5c48BB2A098A44cf6f73", + "links": { + "Homepage": "https://https://10grans.cash" + }, + "marketcap_usd": 0, + "name": "10grans", + "network": "ubq", + "shortcut": "GRANS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "erc20:ubq:INK": { + "address": "0x7845fCbE28ac19ab7ec1C1D9674E34fdCB4917Db", + "links": { + "Homepage": "https://tentacle.finance" + }, + "marketcap_usd": 0, + "name": "INK", + "network": "ubq", + "shortcut": "INK", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "erc20:ubq:QWARK": { "address": "0x4b4899a10F3E507DB207b0ee2426029eFa168a67", "links": { @@ -32622,6 +32771,29 @@ } ] }, + "erc20:ubq:SNARG": { + "address": "0x497E20586F86c35592FF8F65CdE94F296514C387", + "links": { + "Homepage": "https://snarg01.horse" + }, + "marketcap_usd": 0, + "name": "Snarg01", + "network": "ubq", + "shortcut": "SNARG", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "erc20", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:$OC": { "links": { "Homepage": "https://digitalnext.business/SocialSmartChain" @@ -32685,6 +32857,27 @@ } ] }, + "eth:AAC": { + "links": { + "Homepage": "https://www.acuteangle.com/" + }, + "marketcap_usd": 0, + "name": "Double-A Chain", + "shortcut": "AAC", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:ACA": { "links": { "Homepage": "https://acala.network" @@ -32710,7 +32903,7 @@ "links": { "Homepage": "https://akroma.io" }, - "marketcap_usd": 286848, + "marketcap_usd": 18361, "name": "Akroma", "shortcut": "AKA", "t1_enabled": "yes", @@ -32833,8 +33026,8 @@ "links": { "Homepage": "https://www.avax.network/" }, - "marketcap_usd": 27152873099, - "name": "Avalanche", + "marketcap_usd": 0, + "name": "Avalanche C-Chain", "shortcut": "AVAX", "t1_enabled": "yes", "t2_enabled": "yes", @@ -32850,11 +33043,32 @@ } ] }, + "eth:BCS": { + "links": { + "Homepage": "https://blockchainstation.io" + }, + "marketcap_usd": 0, + "name": "BlockChain Station", + "shortcut": "BCS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:BNB": { "links": { "Homepage": "https://www.binance.org" }, - "marketcap_usd": 0, + "marketcap_usd": 72574315643, "name": "Binance Smart Chain", "shortcut": "BNB", "t1_enabled": "yes", @@ -32871,6 +33085,48 @@ } ] }, + "eth:BOY": { + "links": { + "Homepage": "https://boyanet.org" + }, + "marketcap_usd": 0, + "name": "BON Network", + "shortcut": "BOY", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:BRO": { + "links": { + "Homepage": "https://brochain.org" + }, + "marketcap_usd": 0, + "name": "BROChain", + "shortcut": "BRO", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:BTA": { "links": { "Homepage": "https://bitcoinasset.io/" @@ -32955,13 +33211,13 @@ } ] }, - "eth:BTX": { + "eth:CATE": { "links": { - "Homepage": "https://bittexscan.com" + "Homepage": "https://catechain.com" }, "marketcap_usd": 0, - "name": "Bittex", - "shortcut": "BTX", + "name": "Catecoin Chain", + "shortcut": "CATE", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -32976,13 +33232,13 @@ } ] }, - "eth:CATE": { + "eth:CCP": { "links": { - "Homepage": "https://catechain.com" + "Homepage": "https://www.cryptocoinpay.co" }, "marketcap_usd": 0, - "name": "Catecoin Chain", - "shortcut": "CATE", + "name": "CryptoCoinPay", + "shortcut": "CCP", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -33001,7 +33257,7 @@ "links": { "Homepage": "https://docs.celo.org/" }, - "marketcap_usd": 1808214872, + "marketcap_usd": 1500894021, "name": "Celo", "shortcut": "CELO", "t1_enabled": "yes", @@ -33018,12 +33274,54 @@ } ] }, + "eth:CFX": { + "links": { + "Homepage": "https://confluxnetwork.org" + }, + "marketcap_usd": 0, + "name": "Conflux eSpace", + "shortcut": "CFX", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:CLASS": { + "links": { + "Homepage": "https://velaverse.io" + }, + "marketcap_usd": 0, + "name": "Vela1 Chain", + "shortcut": "CLASS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:CLO": { "coinmarketcap_alias": "callisto-network", "links": { "Homepage": "https://callisto.network" }, - "marketcap_usd": 16112568, + "marketcap_usd": 23638622, "name": "Callisto", "shortcut": "CLO", "t1_enabled": "yes", @@ -33044,7 +33342,7 @@ "links": { "Homepage": "https://clover.finance" }, - "marketcap_usd": 168856591, + "marketcap_usd": 108647118, "name": "Clover", "shortcut": "CLV", "t1_enabled": "yes", @@ -33084,9 +33382,9 @@ }, "eth:CRO": { "links": { - "Homepage": "https://cronos.crypto.org" + "Homepage": "https://cronos.org/" }, - "marketcap_usd": 0, + "marketcap_usd": 12473343561, "name": "Cronos", "shortcut": "CRO", "t1_enabled": "yes", @@ -33166,6 +33464,27 @@ } ] }, + "eth:DTH": { + "links": { + "Homepage": "https://dithereum.org" + }, + "marketcap_usd": 0, + "name": "Dithereum", + "shortcut": "DTH", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:DWU": { "links": { "Homepage": "https://decentralized-web.tech/dw_chain.php" @@ -33187,6 +33506,27 @@ } ] }, + "eth:DYNO": { + "links": { + "Homepage": "https://dynoprotocol.com" + }, + "marketcap_usd": 0, + "name": "DYNO", + "shortcut": "DYNO", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:ECO": { "links": { "Homepage": "https://ecoball.org" @@ -33208,11 +33548,32 @@ } ] }, + "eth:ECS": { + "links": { + "Homepage": "https://ecredits.com" + }, + "marketcap_usd": 0, + "name": "eCredits", + "shortcut": "ECS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:EDG": { "links": { "Homepage": "http://edgewa.re" }, - "marketcap_usd": 49689542, + "marketcap_usd": 36805742, "name": "Edgeware", "shortcut": "EDG", "t1_enabled": "yes", @@ -33233,7 +33594,7 @@ "links": { "Homepage": "https://egem.io" }, - "marketcap_usd": 291413, + "marketcap_usd": 274529, "name": "EtherGem", "shortcut": "EGEM", "t1_enabled": "yes", @@ -33250,12 +33611,33 @@ } ] }, + "eth:EIDI": { + "links": { + "Homepage": "https://idchain.one/begin/" + }, + "marketcap_usd": 0, + "name": "IDChain", + "shortcut": "EIDI", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:ELA:20": { "links": { "Homepage": "https://www.elastos.org/" }, "marketcap_usd": 0, - "name": "ELA-ETH-Sidechain", + "name": "Elastos Smart Chain", "shortcut": "ELA", "t1_enabled": "yes", "t2_enabled": "yes", @@ -33313,6 +33695,27 @@ } ] }, + "eth:ENTER": { + "links": { + "Homepage": "https://entercoin.net" + }, + "marketcap_usd": 0, + "name": "EnterChain", + "shortcut": "ENTER", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:ES": { "links": { "Homepage": "https://eraswap.info/" @@ -33360,7 +33763,7 @@ "links": { "Homepage": "https://ethereumclassic.org" }, - "marketcap_usd": 4942917940, + "marketcap_usd": 6700838273, "name": "Ethereum Classic", "shortcut": "ETC", "t1_enabled": "yes", @@ -33377,7 +33780,7 @@ "links": { "Homepage": "https://ethereum.org" }, - "marketcap_usd": 480480777240, + "marketcap_usd": 414331189791, "name": "Ethereum", "shortcut": "ETH", "t1_enabled": "yes", @@ -33415,7 +33818,7 @@ "links": { "Homepage": "https://einc.io" }, - "marketcap_usd": 211185, + "marketcap_usd": 202770, "name": "EtherInc", "shortcut": "ETI", "t1_enabled": "yes", @@ -33453,6 +33856,27 @@ } ] }, + "eth:EVA": { + "links": { + "Homepage": "https://evanesco.org/" + }, + "marketcap_usd": 0, + "name": "Evanesco", + "shortcut": "EVA", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:EVC": { "links": { "Homepage": "https://evrice.com" @@ -33474,6 +33898,27 @@ } ] }, + "eth:EVMOS": { + "links": { + "Homepage": "https://evmos.org" + }, + "marketcap_usd": 0, + "name": "Evmos", + "shortcut": "EVMOS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:EWT": { "links": { "Homepage": "https://energyweb.org" @@ -33583,7 +34028,7 @@ "links": { "Homepage": "https://www.fusion.org/" }, - "marketcap_usd": 62582230, + "marketcap_usd": 37044301, "name": "Fusion", "shortcut": "FSN", "t1_enabled": "yes", @@ -33642,6 +34087,27 @@ } ] }, + "eth:GAR:90": { + "links": { + "Homepage": "https://garizon.com" + }, + "marketcap_usd": 0, + "name": "Garizon Stage0", + "shortcut": "GAR", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:GEN": { "links": { "Homepage": "https://www.xixoio.com/" @@ -33667,7 +34133,7 @@ "links": { "Homepage": "https://moonbeam.network/networks/moonbeam/" }, - "marketcap_usd": 0, + "marketcap_usd": 698883148, "name": "Moonbeam", "shortcut": "GLMR", "t1_enabled": "yes", @@ -33684,11 +34150,32 @@ } ] }, + "eth:GNC": { + "links": { + "Homepage": "https://genesis-gn.com" + }, + "marketcap_usd": 0, + "name": "Genesis Coin", + "shortcut": "GNC", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:GO": { "links": { "Homepage": "https://gochain.io" }, - "marketcap_usd": 40579328, + "marketcap_usd": 31006162, "name": "GoChain", "shortcut": "GO", "t1_enabled": "yes", @@ -33814,7 +34301,7 @@ "links": { "Homepage": "https://hpb.io" }, - "marketcap_usd": 7623236, + "marketcap_usd": 2747057, "name": "High Performance Blockchain", "shortcut": "HPB", "t1_enabled": "yes", @@ -33873,6 +34360,27 @@ } ] }, + "eth:IORA": { + "links": { + "Homepage": "https://iorachain.com" + }, + "marketcap_usd": 0, + "name": "Iora Chain", + "shortcut": "IORA", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:IOTX": { "links": { "Homepage": "https://iotex.io" @@ -33915,6 +34423,27 @@ } ] }, + "eth:JEWEL:53935": { + "links": { + "Homepage": "https://defikingdoms.com" + }, + "marketcap_usd": 0, + "name": "DFK Chain", + "shortcut": "JEWEL", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:JOYS": { "links": { "Homepage": "https://joys.digital" @@ -33982,7 +34511,7 @@ "links": { "Homepage": "https://www.klaytn.com/" }, - "marketcap_usd": 3414586765, + "marketcap_usd": 3437934158, "name": "Klaytn", "shortcut": "KLAY", "t1_enabled": "yes", @@ -34062,6 +34591,27 @@ } ] }, + "eth:LA": { + "links": { + "Homepage": "https://lachain.io" + }, + "marketcap_usd": 0, + "name": "LACHAIN", + "shortcut": "LA", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:LISINSKI": { "links": { "Homepage": "https://lisinski.online" @@ -34087,7 +34637,7 @@ "links": { "Homepage": "https://mathchain.org" }, - "marketcap_usd": 47429180, + "marketcap_usd": 27558250, "name": "MathChain", "shortcut": "MATH", "t1_enabled": "yes", @@ -34108,7 +34658,7 @@ "links": { "Homepage": "https://polygon.technology/" }, - "marketcap_usd": 19946558020, + "marketcap_usd": 13214060845, "name": "Polygon", "shortcut": "MATIC", "t1_enabled": "yes", @@ -34129,7 +34679,7 @@ "links": { "Homepage": "https://metadium.com" }, - "marketcap_usd": 187258505, + "marketcap_usd": 151047691, "name": "Metadium", "shortcut": "META", "t1_enabled": "yes", @@ -34234,7 +34784,7 @@ "links": { "Homepage": "https://moonbeam.network/networks/moonriver/" }, - "marketcap_usd": 473659671, + "marketcap_usd": 276099908, "name": "Moonriver", "shortcut": "MOVR", "t1_enabled": "yes", @@ -34251,27 +34801,6 @@ } ] }, - "eth:MSHD": { - "links": { - "Homepage": "https://docs.moonbeam.network/networks/overview/" - }, - "marketcap_usd": 0, - "name": "Moonshadow", - "shortcut": "MSHD", - "t1_enabled": "yes", - "t2_enabled": "yes", - "type": "coin", - "wallet": [ - { - "name": "MyCrypto", - "url": "https://mycrypto.com" - }, - { - "name": "MyEtherWallet", - "url": "https://www.myetherwallet.com" - } - ] - }, "eth:MTR": { "links": { "Homepage": "https://www.meter.io" @@ -34360,7 +34889,7 @@ "links": { "Homepage": "https://www.newtonproject.org/" }, - "marketcap_usd": 6041033, + "marketcap_usd": 18214812, "name": "Newton", "shortcut": "NEW", "t1_enabled": "yes", @@ -34402,7 +34931,7 @@ "links": { "Homepage": "https://www.energi.world/" }, - "marketcap_usd": 65329552, + "marketcap_usd": 36022511, "name": "Energi", "shortcut": "NRG", "t1_enabled": "yes", @@ -34440,13 +34969,13 @@ } ] }, - "eth:OETH": { + "eth:OKT": { "links": { - "Homepage": "https://optimism.io" + "Homepage": "https://www.okex.com/okexchain" }, "marketcap_usd": 0, - "name": "Optimistic Ethereum", - "shortcut": "OETH", + "name": "OKXChain", + "shortcut": "OKT", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -34461,13 +34990,13 @@ } ] }, - "eth:OKT": { + "eth:OLO": { "links": { - "Homepage": "https://www.okex.com/okexchain" + "Homepage": "https://ibdt.io" }, "marketcap_usd": 0, - "name": "OKExChain", - "shortcut": "OKT", + "name": "TOOL Global", + "shortcut": "OLO", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -34482,13 +35011,13 @@ } ] }, - "eth:OLO": { + "eth:OLT": { "links": { - "Homepage": "https://ibdt.io" + "Homepage": "https://oneledger.io" }, - "marketcap_usd": 0, - "name": "TOOL Global", - "shortcut": "OLO", + "marketcap_usd": 10546673, + "name": "OneLedger", + "shortcut": "OLT", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -34503,13 +35032,13 @@ } ] }, - "eth:OLT": { + "eth:OML": { "links": { - "Homepage": "https://oneledger.io" + "Homepage": "https://omlira.com" }, - "marketcap_usd": 21263702, - "name": "OneLedger", - "shortcut": "OLT", + "marketcap_usd": 0, + "name": "omChain", + "shortcut": "OML", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -34528,7 +35057,7 @@ "links": { "Homepage": "https://www.harmony.one/" }, - "marketcap_usd": 3021520028, + "marketcap_usd": 1964167063, "name": "Harmony", "shortcut": "ONE", "t1_enabled": "yes", @@ -34549,7 +35078,7 @@ "links": { "Homepage": "https://www.harmony.one/" }, - "marketcap_usd": 3021520028, + "marketcap_usd": 1964167063, "name": "Harmony", "shortcut": "ONE", "t1_enabled": "yes", @@ -34570,7 +35099,7 @@ "links": { "Homepage": "https://www.harmony.one/" }, - "marketcap_usd": 3021520028, + "marketcap_usd": 1964167063, "name": "Harmony", "shortcut": "ONE", "t1_enabled": "yes", @@ -34591,7 +35120,7 @@ "links": { "Homepage": "https://www.harmony.one/" }, - "marketcap_usd": 3021520028, + "marketcap_usd": 1964167063, "name": "Harmony", "shortcut": "ONE", "t1_enabled": "yes", @@ -34612,7 +35141,7 @@ "links": { "Homepage": "https://ont.io/" }, - "marketcap_usd": 640702328, + "marketcap_usd": 569997705, "name": "Ontology", "shortcut": "ONG", "t1_enabled": "yes", @@ -34629,6 +35158,27 @@ } ] }, + "eth:OY": { + "links": { + "Homepage": "https://www.oychain.io" + }, + "marketcap_usd": 0, + "name": "OYchain", + "shortcut": "OY", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:PALM": { "links": { "Homepage": "https://palm.io" @@ -34675,7 +35225,7 @@ "links": { "Homepage": "https://explorer.lightstreams.io" }, - "marketcap_usd": 775028, + "marketcap_usd": 627796, "name": "Lightstreams", "shortcut": "PHT", "t1_enabled": "yes", @@ -34692,11 +35242,32 @@ } ] }, + "eth:PHX": { + "links": { + "Homepage": "https://cryptophoenix.org/phoenix" + }, + "marketcap_usd": 0, + "name": "Phoenix", + "shortcut": "PHX", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:PIRL": { "links": { "Homepage": "https://pirl.io" }, - "marketcap_usd": 42177, + "marketcap_usd": 0, "name": "Pirl", "shortcut": "PIRL", "t1_enabled": "yes", @@ -34759,7 +35330,7 @@ "links": { "Homepage": "https://poa.network" }, - "marketcap_usd": 87968568, + "marketcap_usd": 31041684, "name": "POA Network Core", "shortcut": "POA", "t1_enabled": "yes", @@ -34776,6 +35347,27 @@ } ] }, + "eth:POLIS": { + "links": { + "Homepage": "https://polis.tech" + }, + "marketcap_usd": 1569555, + "name": "Polis", + "shortcut": "POLIS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:POP": { "links": { "Homepage": "https://popcateum.org" @@ -34797,11 +35389,32 @@ } ] }, + "eth:PRB": { + "links": { + "Homepage": "https://net.paribu.com" + }, + "marketcap_usd": 0, + "name": "Paribu Net", + "shortcut": "PRB", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:QKC:100000": { "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34822,7 +35435,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34843,7 +35456,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34864,7 +35477,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34885,7 +35498,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34906,7 +35519,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34927,7 +35540,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34948,7 +35561,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -34969,7 +35582,7 @@ "links": { "Homepage": "https://www.quarkchain.io/" }, - "marketcap_usd": 145939896, + "marketcap_usd": 148630106, "name": "QuarkChain", "shortcut": "QKC", "t1_enabled": "yes", @@ -35009,7 +35622,7 @@ }, "eth:RBD": { "links": { - "Homepage": "http://wegochain.io" + "Homepage": "https://www.wegochain.io" }, "marketcap_usd": 0, "name": "Wegochain Rubidium", @@ -35049,6 +35662,27 @@ } ] }, + "eth:REI:47805": { + "links": { + "Homepage": "https://rei.network/" + }, + "marketcap_usd": 0, + "name": "REI Network", + "shortcut": "REI", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:RNA": { "links": { "Homepage": "https://scan.genechain.io/" @@ -35072,7 +35706,7 @@ }, "eth:ROC": { "links": { - "Homepage": "" + "Homepage": "https://docs.moonbeam.network/learn/platform/networks/overview/" }, "marketcap_usd": 0, "name": "Moonrock", @@ -35116,7 +35750,7 @@ "links": { "Homepage": "https://rangersprotocol.com" }, - "marketcap_usd": 18214685, + "marketcap_usd": 6660496, "name": "Rangers Protocol", "shortcut": "RPG", "t1_enabled": "yes", @@ -35175,6 +35809,27 @@ } ] }, + "eth:SETM": { + "links": { + "Homepage": "https://setheum.xyz" + }, + "marketcap_usd": 0, + "name": "Setheum", + "shortcut": "SETM", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:SGB": { "links": { "Homepage": "https://flare.xyz" @@ -35221,7 +35876,7 @@ "links": { "Homepage": "https://clover.finance/sakura" }, - "marketcap_usd": 7257052, + "marketcap_usd": 3417233, "name": "Sakura", "shortcut": "SKU", "t1_enabled": "yes", @@ -35238,13 +35893,13 @@ } ] }, - "eth:SOTER": { + "eth:SNT": { "links": { - "Homepage": "https://www.soterone.com" + "Homepage": "https://novanetwork.io" }, "marketcap_usd": 0, - "name": "SoterOne", - "shortcut": "SOTER", + "name": "Nova Network", + "shortcut": "SNT", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35259,13 +35914,13 @@ } ] }, - "eth:SPARK": { + "eth:SOTER": { "links": { - "Homepage": "https://docs.fuse.io/general/fuse-network-blockchain/fuse-testnet" + "Homepage": "https://www.soterone.com" }, "marketcap_usd": 0, - "name": "Fuse Sparknet", - "shortcut": "SPARK", + "name": "SoterOne", + "shortcut": "SOTER", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35280,13 +35935,13 @@ } ] }, - "eth:SPOA": { + "eth:SPARK": { "links": { - "Homepage": "https://poa.network" + "Homepage": "https://docs.fuse.io/general/fuse-network-blockchain/fuse-testnet" }, "marketcap_usd": 0, - "name": "POA Network Sokol", - "shortcut": "SPOA", + "name": "Fuse Sparknet", + "shortcut": "SPARK", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35301,13 +35956,13 @@ } ] }, - "eth:SRN": { + "eth:SPOA": { "links": { - "Homepage": "https://surnet.org" + "Homepage": "https://poa.network" }, "marketcap_usd": 0, - "name": "SUR Blockchain Network", - "shortcut": "SRN", + "name": "POA Network Sokol", + "shortcut": "SPOA", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35322,13 +35977,13 @@ } ] }, - "eth:SYS": { + "eth:SRN": { "links": { - "Homepage": "https://www.syscoin.org" + "Homepage": "https://surnet.org" }, - "marketcap_usd": 507953217, - "name": "Syscoin", - "shortcut": "SYS", + "marketcap_usd": 0, + "name": "SUR Blockchain Network", + "shortcut": "SRN", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35347,7 +36002,7 @@ "links": { "Homepage": "https://seelen.pro/" }, - "marketcap_usd": 1577405, + "marketcap_usd": 4647879, "name": "Seele", "shortcut": "Seele", "t1_enabled": "yes", @@ -35427,6 +36082,27 @@ } ] }, + "eth:TELE:8000": { + "links": { + "Homepage": "https://teleport.network" + }, + "marketcap_usd": 0, + "name": "Teleport", + "shortcut": "TELE", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:TFI": { "links": { "Homepage": "https://exp.thaifi.com" @@ -35469,11 +36145,11 @@ } ] }, - "eth:TOMO": { + "eth:TOMO:88": { "links": { - "Homepage": "https://tomocoin.io" + "Homepage": "https://tomochain.com" }, - "marketcap_usd": 180638533, + "marketcap_usd": 133836594, "name": "TomoChain", "shortcut": "TOMO", "t1_enabled": "yes", @@ -35557,7 +36233,7 @@ "links": { "Homepage": "https://thundercore.com" }, - "marketcap_usd": 0, + "marketcap_usd": 86352456, "name": "ThunderCore", "shortcut": "TT", "t1_enabled": "yes", @@ -35595,11 +36271,32 @@ } ] }, + "eth:UBC": { + "links": { + "Homepage": "https://www.ubchain.site/" + }, + "marketcap_usd": 0, + "name": "UB Smart Chain", + "shortcut": "UBC", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:UBQ": { "links": { "Homepage": "https://ubiqsmart.com" }, - "marketcap_usd": 6159117, + "marketcap_usd": 3779184, "name": "Ubiq", "shortcut": "UBQ", "t1_enabled": "yes", @@ -35679,11 +36376,74 @@ } ] }, + "eth:VS:888888": { + "links": { + "Homepage": "https://www.v.network" + }, + "marketcap_usd": 0, + "name": "Vision -", + "shortcut": "VS", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:W3G": { + "links": { + "Homepage": "https://web3games.org/" + }, + "marketcap_usd": 0, + "name": "Web3Games Devnet", + "shortcut": "W3G", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:W3Q:333": { + "links": { + "Homepage": "https://web3q.io/home.w3q/" + }, + "marketcap_usd": 0, + "name": "Web3Q", + "shortcut": "W3Q", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:WAN": { "links": { "Homepage": "https://www.wanscan.org" }, - "marketcap_usd": 139993716, + "marketcap_usd": 105653679, "name": "Wanchain", "shortcut": "WAN", "t1_enabled": "yes", @@ -35725,6 +36485,27 @@ } ] }, + "eth:WGM": { + "links": { + "Homepage": "https://trywagmi.xyz" + }, + "marketcap_usd": 0, + "name": "WAGMI", + "shortcut": "WGM", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:WTT": { "links": { "Homepage": "http://www.cadaut.com" @@ -35809,7 +36590,7 @@ "links": { "Homepage": "https://www.singularity.gold" }, - "marketcap_usd": 1281101, + "marketcap_usd": 279637, "name": "Singularity ZERO", "shortcut": "ZERO", "t1_enabled": "yes", @@ -35847,13 +36628,13 @@ } ] }, - "eth:aETH:1313161554": { + "eth:atp": { "links": { - "Homepage": "https://aurora.dev" + "Homepage": "https://www.alaya.network/" }, - "marketcap_usd": 16672966, - "name": "Aurora", - "shortcut": "aETH", + "marketcap_usd": 0, + "name": "Alaya", + "shortcut": "atp", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35868,13 +36649,13 @@ } ] }, - "eth:atp": { + "eth:cTH": { "links": { - "Homepage": "https://www.alaya.network/" + "Homepage": "https://cheapeth.org/" }, "marketcap_usd": 0, - "name": "Alaya", - "shortcut": "atp", + "name": "cheapETH", + "shortcut": "cTH", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35889,13 +36670,13 @@ } ] }, - "eth:cTH": { + "eth:cet": { "links": { - "Homepage": "https://cheapeth.org/" + "Homepage": "https://www.coinex.org/" }, "marketcap_usd": 0, - "name": "cheapETH", - "shortcut": "cTH", + "name": "CoinEx Smart Chain", + "shortcut": "cet", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35910,13 +36691,13 @@ } ] }, - "eth:cet": { + "eth:lat": { "links": { - "Homepage": "https://www.coinex.org/" + "Homepage": "https://www.platon.network" }, - "marketcap_usd": 0, - "name": "CoinEx Smart Chain", - "shortcut": "cet", + "marketcap_usd": 141608249, + "name": "PlatON", + "shortcut": "lat", "t1_enabled": "yes", "t2_enabled": "yes", "type": "coin", @@ -35952,11 +36733,154 @@ } ] }, + "eth:tGOR:5": { + "links": { + "Homepage": "https://goerli.net/#about" + }, + "marketcap_usd": 0, + "name": "G\u00f6rli", + "shortcut": "tGOR", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:tKOR": { + "links": { + "Homepage": "https://optimism.io" + }, + "marketcap_usd": 0, + "name": "Optimism Kovan", + "shortcut": "tKOR", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:tKOV": { + "links": { + "Homepage": "https://kovan-testnet.github.io/website" + }, + "marketcap_usd": 0, + "name": "Kovan", + "shortcut": "tKOV", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:tMATIC": { + "links": { + "Homepage": "https://polygon.technology/" + }, + "marketcap_usd": 0, + "name": "Mumbai", + "shortcut": "tMATIC", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:tRIN": { + "links": { + "Homepage": "https://www.rinkeby.io" + }, + "marketcap_usd": 0, + "name": "Rinkeby", + "shortcut": "tRIN", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, + "eth:tROP": { + "links": { + "Homepage": "https://github.com/ethereum/ropsten" + }, + "marketcap_usd": 0, + "name": "Ropsten", + "shortcut": "tROP", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "Trezor Suite", + "url": "https://suite.trezor.io" + } + ] + }, + "eth:tSEP": { + "links": { + "Homepage": "https://sepolia.otterscan.io" + }, + "marketcap_usd": 0, + "name": "Sepolia", + "shortcut": "tSEP", + "t1_enabled": "yes", + "t2_enabled": "yes", + "type": "coin", + "wallet": [ + { + "name": "MyCrypto", + "url": "https://mycrypto.com" + }, + { + "name": "MyEtherWallet", + "url": "https://www.myetherwallet.com" + } + ] + }, "eth:xDAI:100": { "links": { "Homepage": "https://www.xdaichain.com/" }, - "marketcap_usd": 116800679, + "marketcap_usd": 137755196, "name": "Gnosis Chain (formerly xDai)", "shortcut": "xDAI", "t1_enabled": "yes", @@ -35975,10 +36899,10 @@ }, "misc:ADA": { "links": { - "Github": "https://github.com/input-output-hk/cardano-sl", + "Github": "https://github.com/input-output-hk/cardano-node", "Homepage": "https://www.cardano.org" }, - "marketcap_usd": 48097273891, + "marketcap_usd": 41113378035, "name": "Cardano", "shortcut": "ADA", "t1_enabled": "no", @@ -35986,16 +36910,8 @@ "type": "coin", "wallet": [ { - "name": "AdaLite", - "url": "https://adalite.io/app" - }, - { - "name": "Daedalus", - "url": "https://daedaluswallet.io" - }, - { - "name": "Yoroi", - "url": "https://yoroi-wallet.com" + "name": "Trezor Suite", + "url": "https://suite.trezor.io" } ] }, @@ -36003,7 +36919,7 @@ "links": { "Homepage": "https://binance.org" }, - "marketcap_usd": 0, + "marketcap_usd": 72574315643, "name": "Binance Chain", "shortcut": "BNB", "t1_enabled": "no", @@ -36021,7 +36937,7 @@ "Github": "https://github.com/EOSIO/eos", "Homepage": "https://eos.io" }, - "marketcap_usd": 3273993160, + "marketcap_usd": 2866062223, "name": "EOS", "shortcut": "EOS", "t1_enabled": "no", @@ -36039,7 +36955,7 @@ "Github": "https://github.com/maidsafe", "Homepage": "https://maidsafe.net" }, - "marketcap_usd": 167286778, + "marketcap_usd": 170536952, "name": "MaidSafeCoin", "shortcut": "MAID", "t1_enabled": "yes", @@ -36052,7 +36968,7 @@ "Github": "https://github.com/OmniLayer", "Homepage": "https://www.omnilayer.org" }, - "marketcap_usd": 1901654, + "marketcap_usd": 1861833, "name": "Omni", "shortcut": "OMNI", "t1_enabled": "yes", @@ -36064,7 +36980,7 @@ "links": { "Homepage": "https://tether.to" }, - "marketcap_usd": 78076571697, + "marketcap_usd": 81569830177, "name": "Tether", "shortcut": "USDT", "t1_enabled": "yes", @@ -36077,7 +36993,7 @@ "Github": "https://github.com/stellar/stellar-core", "Homepage": "https://www.stellar.org" }, - "marketcap_usd": 7150167072, + "marketcap_usd": 5859115983, "name": "Stellar", "shortcut": "XLM", "t1_enabled": "yes", @@ -36103,7 +37019,7 @@ "Github": "https://github.com/monero-project/monero", "Homepage": "https://getmonero.org" }, - "marketcap_usd": 3787673389, + "marketcap_usd": 4055386351, "name": "Monero", "shortcut": "XMR", "t1_enabled": "no", @@ -36121,7 +37037,7 @@ "Github": "https://github.com/ripple/rippled", "Homepage": "https://ripple.com" }, - "marketcap_usd": 43617409679, + "marketcap_usd": 42166029829, "name": "Ripple", "shortcut": "XRP", "t1_enabled": "no", @@ -36143,7 +37059,7 @@ "Github": "https://github.com/tezos/tezos", "Homepage": "https://tezos.com" }, - "marketcap_usd": 4174884531, + "marketcap_usd": 3458159408, "name": "Tezos", "shortcut": "XTZ", "t1_enabled": "no", @@ -36246,7 +37162,7 @@ "links": { "Homepage": "https://nemplatform.com" }, - "marketcap_usd": 1255848019, + "marketcap_usd": 1096201929, "name": "NEM", "shortcut": "XEM", "t1_enabled": "yes", @@ -36261,12 +37177,12 @@ } }, "info": { - "marketcap_supported": "92.66 %", - "marketcap_usd": 2180198112845, - "t1_coins": 1838, - "t2_coins": 1844, - "total_marketcap_usd": 2352887028158, - "updated_at": 1640521595, - "updated_at_readable": "Sun Dec 26 13:26:35 2021" + "marketcap_supported": "97.62 %", + "marketcap_usd": 2108186706857, + "t1_coins": 1878, + "t2_coins": 1884, + "total_marketcap_usd": 2159495066042, + "updated_at": 1648568699, + "updated_at_readable": "Tue Mar 29 17:44:59 2022" } } diff --git a/common/defs/ethereum/chains b/common/defs/ethereum/chains index c2dcfd82e..427b06281 160000 --- a/common/defs/ethereum/chains +++ b/common/defs/ethereum/chains @@ -1 +1 @@ -Subproject commit c2dcfd82e737d894044635f9cb4f0a6d8cf0d158 +Subproject commit 427b0628145b86911ffe571bb1ced0ca883c48f5 diff --git a/common/defs/ethereum/tokens b/common/defs/ethereum/tokens index 502ed9102..9045282fc 160000 --- a/common/defs/ethereum/tokens +++ b/common/defs/ethereum/tokens @@ -1 +1 @@ -Subproject commit 502ed91029c4b5c89f5059f561cc98fa346fdda2 +Subproject commit 9045282fce6e3b40f6bbed29ce9bf8a86d415cf3 diff --git a/common/defs/support.json b/common/defs/support.json index 2ef56f3d4..e6a21daaa 100644 --- a/common/defs/support.json +++ b/common/defs/support.json @@ -202,6 +202,7 @@ "erc20:eth:AEUR": "1.9.0", "erc20:eth:AFA": "1.8.0", "erc20:eth:AGI": "1.6.2", + "erc20:eth:AGRS": "1.10.6", "erc20:eth:AGS": "1.9.0", "erc20:eth:AI": "1.8.0", "erc20:eth:AID": "1.8.0", @@ -213,6 +214,7 @@ "erc20:eth:ALEPH": "1.9.5", "erc20:eth:ALI": "1.8.0", "erc20:eth:ALIS": "1.6.2", + "erc20:eth:ALTA": "1.10.6", "erc20:eth:ALTS": "1.6.2", "erc20:eth:ALX": "1.8.0", "erc20:eth:AMB": "1.6.2", @@ -408,7 +410,6 @@ "erc20:eth:CHP": "1.8.0", "erc20:eth:CHSB": "1.6.2", "erc20:eth:CHX": "1.8.0", - "erc20:eth:CIG": "1.9.0", "erc20:eth:CIV": "1.10.5", "erc20:eth:CIYA": "1.8.0", "erc20:eth:CJT": "1.8.0", @@ -425,6 +426,7 @@ "erc20:eth:CMERGE": "1.10.5", "erc20:eth:CNB": "1.6.2", "erc20:eth:CND": "1.6.2", + "erc20:eth:CNDL": "1.10.6", "erc20:eth:CNN": "1.8.0", "erc20:eth:CO2": "1.6.2", "erc20:eth:CO2Bit": "1.6.2", @@ -480,7 +482,7 @@ "erc20:eth:DAB": "1.6.2", "erc20:eth:DACS": "1.8.0", "erc20:eth:DADI": "1.6.2", - "erc20:eth:DAI": "1.8.0", + "erc20:eth:DAF": "1.10.6", "erc20:eth:DALC": "1.6.2", "erc20:eth:DAN": "1.6.2", "erc20:eth:DAT": "1.6.2", @@ -505,7 +507,6 @@ "erc20:eth:DEW": "1.8.0", "erc20:eth:DEX": "1.8.0", "erc20:eth:DF": "1.9.0", - "erc20:eth:DGD": "1.8.0", "erc20:eth:DGPT": "1.6.2", "erc20:eth:DGS": "1.6.3", "erc20:eth:DGX": "1.6.2", @@ -699,7 +700,6 @@ "erc20:eth:GL": "1.9.1", "erc20:eth:GLA": "1.8.0", "erc20:eth:GNO": "1.6.2", - "erc20:eth:GNT": "1.8.0", "erc20:eth:GNX": "1.8.0", "erc20:eth:GNY": "1.8.0", "erc20:eth:GOLDX": "1.6.2", @@ -720,7 +720,6 @@ "erc20:eth:GTO": "1.6.2", "erc20:eth:GUESS": "1.8.0", "erc20:eth:GULD": "1.6.3", - "erc20:eth:GUP": "1.8.0", "erc20:eth:GUSD": "1.8.0", "erc20:eth:GVT": "1.6.2", "erc20:eth:GXC": "1.6.2", @@ -827,7 +826,6 @@ "erc20:eth:JSE": "1.9.0", "erc20:eth:KAN": "1.8.0", "erc20:eth:KAPA": "1.8.4", - "erc20:eth:KC": "1.8.0", "erc20:eth:KCS": "1.9.0", "erc20:eth:KEE": "1.6.2", "erc20:eth:KIN": "1.6.2", @@ -888,6 +886,7 @@ "erc20:eth:LRC": "1.6.2", "erc20:eth:LRC (old):deprecated": "1.9.0", "erc20:eth:LUC": "1.6.2", + "erc20:eth:LUCHOW": "1.10.6", "erc20:eth:LUCK": "1.6.2", "erc20:eth:LULU": "1.9.0", "erc20:eth:LUM": "1.6.2", @@ -909,6 +908,7 @@ "erc20:eth:MDA": "1.6.2", "erc20:eth:MDT": "1.8.0", "erc20:eth:MDX": "1.9.5", + "erc20:eth:MEDCASH": "1.10.6", "erc20:eth:MEDX": "1.8.0", "erc20:eth:MEME": "1.9.5", "erc20:eth:MESG": "1.8.4", @@ -926,10 +926,7 @@ "erc20:eth:MINDS": "1.10.3", "erc20:eth:MITH": "1.9.0", "erc20:eth:MITX": "1.8.0", - "erc20:eth:MKR": "1.8.0", "erc20:eth:MKT": "1.6.2", - "erc20:eth:MLN (new)": "1.8.0", - "erc20:eth:MLN (old):deprecated": "1.8.0", "erc20:eth:MM": "1.10.4", "erc20:eth:MNE": "1.6.2", "erc20:eth:MNL": "1.9.5", @@ -988,7 +985,6 @@ "erc20:eth:NMR": "1.6.2", "erc20:eth:NOAH": "1.8.0", "erc20:eth:NOBS": "1.8.0", - "erc20:eth:NONE": "1.8.0", "erc20:eth:NOT": "1.9.0", "erc20:eth:NOX": "1.6.2", "erc20:eth:NPER": "1.6.2", @@ -1150,7 +1146,6 @@ "erc20:eth:RBT": "1.9.3", "erc20:eth:RBX": "1.10.5", "erc20:eth:RCN": "1.6.2", - "erc20:eth:RDN": "1.8.0", "erc20:eth:RDV": "1.9.0", "erc20:eth:REA": "1.6.2", "erc20:eth:REAL": "1.8.0", @@ -1162,8 +1157,6 @@ "erc20:eth:REM": "1.8.0", "erc20:eth:REMI": "1.8.0", "erc20:eth:REN": "1.6.2", - "erc20:eth:REP": "1.8.0", - "erc20:eth:REP:deprecated": "1.8.0", "erc20:eth:REPv2": "1.9.4", "erc20:eth:REQ": "1.6.2", "erc20:eth:RET": "1.9.0", @@ -1176,7 +1169,6 @@ "erc20:eth:RIPT": "1.6.2", "erc20:eth:RIYA": "1.8.0", "erc20:eth:RKT": "1.8.0", - "erc20:eth:RLC": "1.6.2", "erc20:eth:RLT": "1.6.2", "erc20:eth:RLTY": "1.6.2", "erc20:eth:RLX": "1.6.2", @@ -1194,6 +1186,7 @@ "erc20:eth:ROUND": "1.6.2", "erc20:eth:RPE": "1.8.4", "erc20:eth:RPL": "1.6.2", + "erc20:eth:RSR": "1.10.6", "erc20:eth:RTB": "1.8.0", "erc20:eth:RTC": "1.8.4", "erc20:eth:RTH": "1.8.0", @@ -1219,6 +1212,7 @@ "erc20:eth:SENT": "1.8.0", "erc20:eth:SET": "1.6.2", "erc20:eth:SETS": "1.9.5", + "erc20:eth:SEV": "1.10.6", "erc20:eth:SEXY": "1.6.2", "erc20:eth:SGA": "1.9.0", "erc20:eth:SGEL": "1.6.2", @@ -1317,6 +1311,7 @@ "erc20:eth:SXR": "1.9.0", "erc20:eth:SXUT": "1.6.2", "erc20:eth:SYN": "1.6.2", + "erc20:eth:SYS": "1.10.6", "erc20:eth:SYSX": "1.9.5", "erc20:eth:SenSatorI": "1.6.2", "erc20:eth:TALAO": "1.8.0", @@ -1472,6 +1467,8 @@ "erc20:eth:WIN": "1.8.0", "erc20:eth:WINGS": "1.6.2", "erc20:eth:WISH": "1.8.0", + "erc20:eth:WLKR": "1.10.6", + "erc20:eth:WLKRR": "1.10.6", "erc20:eth:WMA": "1.10.3", "erc20:eth:WMK": "1.6.3", "erc20:eth:WNK": "1.6.3", @@ -1545,7 +1542,6 @@ "erc20:eth:ZMAN": "1.8.4", "erc20:eth:ZMN": "1.6.2", "erc20:eth:ZPR": "1.8.0", - "erc20:eth:ZRX": "1.8.0", "erc20:eth:ZST": "1.6.2", "erc20:eth:ZTX": "1.8.0", "erc20:eth:ZXC": "1.8.0", @@ -1945,32 +1941,17 @@ "erc20:eth:xOXT": "1.9.0", "erc20:eth:xSOL": "1.9.0", "erc20:kov:Aeternity": "1.6.2", - "erc20:kov:DAI": "1.8.0", - "erc20:kov:DGD": "1.8.0", "erc20:kov:GAV": "1.9.0", - "erc20:kov:GNT": "1.8.0", - "erc20:kov:GUP": "1.8.0", - "erc20:kov:MKR:1dad": "1.9.0", - "erc20:kov:MKR:aaf6": "1.9.0", - "erc20:kov:MLN": "1.8.0", - "erc20:kov:REP": "1.8.0", - "erc20:kov:RLC": "1.9.0", "erc20:kov:TIB": "1.9.0", - "erc20:kov:ZRX": "1.8.0", "erc20:rin:BHNT": "1.6.2", "erc20:rin:CTGA": "1.6.2", - "erc20:rin:KC": "1.8.0", - "erc20:rin:NONE": "1.8.0", "erc20:rin:PPD": "1.6.2", - "erc20:rin:RDN": "1.8.0", - "erc20:rin:RLC": "1.9.0", "erc20:rin:WALL": "1.6.2", "erc20:rin:qwe": "1.9.0", "erc20:rop:*PLASMA": "1.6.3", "erc20:rop:ILSC": "1.6.2", "erc20:rop:MEWV5": "1.9.0", - "erc20:rop:NONE": "1.8.0", - "erc20:rop:RLC": "1.9.0", + "erc20:rop:RCL": "1.10.6", "erc20:rop:dqr30": "1.8.0", "erc20:rsk:ARSCB": "1.10.4", "erc20:rsk:BOBCB": "1.10.4", @@ -2013,11 +1994,20 @@ "erc20:ubq:BEER": "1.6.2", "erc20:ubq:CEFS": "1.6.2", "erc20:ubq:DOT": "1.6.2", + "erc20:ubq:ESCH": "1.10.6", + "erc20:ubq:GEO": "1.10.6", + "erc20:ubq:GRANS": "1.10.6", + "erc20:ubq:INK": "1.10.6", "erc20:ubq:QWARK": "1.6.2", "erc20:ubq:RICKS": "1.6.2", + "erc20:ubq:SNARG": "1.10.6", + "erc20:ubq:SPHR": "1.10.6", + "erc20:ubq:SPHRC": "1.10.6", + "erc20:ubq:TGE1": "1.10.6", "eth:$OC": "1.10.5", "eth:0xF": "1.9.4", "eth:420": "1.9.5", + "eth:AAC": "1.10.6", "eth:ACA": "1.9.5", "eth:AKA": "1.6.3", "eth:AMBR": "1.10.4", @@ -2026,13 +2016,19 @@ "eth:ATS": "1.8.0", "eth:AUX": "1.8.4", "eth:AVAX": "1.9.5", + "eth:BCS": "1.10.6", "eth:BNB": "1.9.4", + "eth:BOY": "1.10.6", + "eth:BRO": "1.10.6", "eth:BTA": "1.10.4", "eth:BTCIX": "1.10.5", "eth:BTM": "1.10.5", "eth:BTT": "1.10.4", "eth:CATE": "1.10.3", + "eth:CCP": "1.10.6", "eth:CELO": "1.9.5", + "eth:CFX": "1.10.6", + "eth:CLASS": "1.10.6", "eth:CLO": "1.6.2", "eth:CLV": "1.10.3", "eth:CRAB": "1.10.5", @@ -2040,13 +2036,18 @@ "eth:DAX": "1.10.3", "eth:DEV": "1.10.4", "eth:DIODE": "1.9.5", + "eth:DTH": "1.10.6", "eth:DWU": "1.10.3", + "eth:DYNO": "1.10.6", "eth:ECO": "1.10.4", + "eth:ECS": "1.10.6", "eth:EDG": "1.10.3", "eth:EGEM": "1.6.2", + "eth:EIDI": "1.10.6", "eth:ELA:20": "1.10.3", "eth:ELLA": "1.6.2", "eth:ELV": "1.10.4", + "eth:ENTER": "1.10.6", "eth:ES": "1.10.3", "eth:ESN": "1.6.3", "eth:ETC": "1.6.2", @@ -2054,7 +2055,9 @@ "eth:ETHO": "1.6.3", "eth:ETI": "1.8.2", "eth:ETL": "1.10.3", + "eth:EVA": "1.10.6", "eth:EVC": "1.10.3", + "eth:EVMOS": "1.10.6", "eth:EWT": "1.9.4", "eth:EXP": "1.6.2", "eth:FETH": "1.10.3", @@ -2063,8 +2066,10 @@ "eth:FSN": "1.10.3", "eth:FTM": "1.9.4", "eth:FUSE": "1.9.4", + "eth:GAR:90": "1.10.6", "eth:GEN": "1.10.3", "eth:GLMR": "1.10.3", + "eth:GNC": "1.10.6", "eth:GO": "1.6.2", "eth:GT": "1.10.3", "eth:GooD": "1.10.3", @@ -2074,8 +2079,10 @@ "eth:HPB": "1.8.2", "eth:HT": "1.9.5", "eth:ILT": "1.9.4", + "eth:IORA": "1.10.6", "eth:IOTX": "1.10.3", "eth:IPOS": "1.9.4", + "eth:JEWEL:53935": "1.10.6", "eth:JOYS": "1.9.5", "eth:KAR": "1.9.5", "eth:KCS": "1.10.3", @@ -2083,6 +2090,7 @@ "eth:KTO:2559": "1.10.3", "eth:L1": "1.10.5", "eth:L99": "1.10.4", + "eth:LA": "1.10.6", "eth:LISINSKI": "1.9.4", "eth:MATH": "1.9.5", "eth:MATIC": "1.9.4", @@ -2092,7 +2100,6 @@ "eth:MIX": "1.7.2", "eth:MOLE": "1.10.5", "eth:MOVR": "1.10.3", - "eth:MSHD": "1.10.3", "eth:MTR": "1.9.5", "eth:MTT": "1.10.3", "eth:MUSIC": "1.6.3", @@ -2101,24 +2108,27 @@ "eth:NEXT": "1.10.5", "eth:NRG": "1.9.4", "eth:NTT": "1.10.5", - "eth:OETH": "1.9.4", "eth:OKT": "1.9.5", "eth:OLO": "1.10.3", "eth:OLT": "1.10.4", + "eth:OML": "1.10.6", "eth:ONE:1666600000": "1.9.5", "eth:ONE:1666600001": "1.9.5", "eth:ONE:1666600002": "1.9.5", "eth:ONE:1666600003": "1.9.5", "eth:ONG": "1.10.3", + "eth:OY": "1.10.6", "eth:PALM": "1.9.5", "eth:PETH": "1.10.3", "eth:PHT": "1.9.4", + "eth:PHX": "1.10.6", "eth:PIRL": "1.6.3", "eth:PIX": "1.10.5", "eth:PLS": "1.10.4", "eth:POA": "1.9.4", "eth:POLIS": "1.10.6", "eth:POP": "1.10.4", + "eth:PRB": "1.10.6", "eth:QKC:100000": "1.10.3", "eth:QKC:100001": "1.10.3", "eth:QKC:100002": "1.10.3", @@ -2131,15 +2141,18 @@ "eth:QKI": "1.10.3", "eth:RBD": "1.9.4", "eth:RBTC": "1.6.2", + "eth:REI:47805": "1.10.6", "eth:RNA": "1.10.3", "eth:ROC": "1.10.3", "eth:ROSE": "1.10.5", "eth:RPG": "1.10.5", "eth:RUPX": "1.9.5", "eth:SDN": "1.10.4", + "eth:SETM": "1.10.6", "eth:SGB": "1.10.3", "eth:SHIB": "1.10.5", "eth:SKU": "1.10.3", + "eth:SNT": "1.10.6", "eth:SOTER": "1.9.5", "eth:SPARK": "1.10.5", "eth:SPOA": "1.10.5", @@ -2149,10 +2162,11 @@ "eth:TBG": "1.9.5", "eth:TCH": "1.9.4", "eth:TCLO": "1.9.4", + "eth:TELE:8000": "1.10.6", "eth:TETC": "1.9.4", "eth:TFI": "1.9.5", "eth:TLOS:40": "1.10.3", - "eth:TOMO": "1.9.4", + "eth:TOMO:88": "1.10.6", "eth:TOYS": "1.9.5", "eth:TPEP": "1.9.4", "eth:TSF": "1.9.4", @@ -2161,22 +2175,27 @@ "eth:TUBQ": "1.9.4", "eth:TXDC": "1.9.5", "eth:U+25B3": "1.9.4", + "eth:UBC": "1.10.6", "eth:UBQ": "1.6.2", "eth:UZMI": "1.10.5", "eth:VAL": "1.9.4", "eth:VLX": "1.10.4", + "eth:VS:888888": "1.10.6", + "eth:W3G": "1.10.6", + "eth:W3Q:333": "1.10.6", "eth:WAN": "1.10.3", "eth:WEB": "1.9.4", + "eth:WGM": "1.10.6", "eth:WTT": "1.10.5", "eth:XDC": "1.9.5", "eth:XERO": "1.9.4", "eth:YETI": "1.9.4", "eth:ZERO": "1.10.5", "eth:ZYX": "1.10.4", - "eth:aETH:1313161554": "1.10.3", "eth:atp": "1.10.5", "eth:cTH": "1.10.3", "eth:cet": "1.10.3", + "eth:lat": "1.10.6", "eth:peggle": "1.9.5", "eth:tATS": "1.8.0", "eth:tAVAX": "1.9.5", @@ -2201,6 +2220,7 @@ "eth:tRBTC": "1.6.2", "eth:tRIN": "1.6.2", "eth:tROP": "1.6.2", + "eth:tSEP": "1.10.6", "eth:tVT": "1.9.4", "eth:thtt": "1.9.5", "eth:tmACA": "1.9.5", @@ -2264,6 +2284,8 @@ "erc20:eth:CCS:315c": "(AUTO) duplicate key", "erc20:eth:CDX:2cb1": "(AUTO) duplicate key", "erc20:eth:CDX:6fff": "(AUTO) duplicate key", + "erc20:eth:CIG:0038": "(AUTO) duplicate key", + "erc20:eth:CIG:cb56": "(AUTO) duplicate key", "erc20:eth:CMT": "Migrated to mainnet", "erc20:eth:COIN:5e8f": "(AUTO) duplicate key", "erc20:eth:COIN:eb54": "(AUTO) duplicate key", @@ -2275,12 +2297,14 @@ "erc20:eth:CRPT:80a7": "(AUTO) duplicate key", "erc20:eth:CTT:1a47": "(AUTO) duplicate key", "erc20:eth:CTT:e3fa": "(AUTO) duplicate key", + "erc20:eth:DAI": "(AUTO) duplicate key", "erc20:eth:DAO:0f51": "(AUTO) duplicate key", "erc20:eth:DAO:bb9b": "(AUTO) duplicate key", "erc20:eth:DATA:0cf0": "(AUTO) duplicate key", "erc20:eth:DATA:8f69": "(AUTO) duplicate key", "erc20:eth:DEPO": "(AUTO) duplicate key", "erc20:eth:DEPO (Depository Network)": "(AUTO) duplicate key", + "erc20:eth:DGD": "(AUTO) duplicate key", "erc20:eth:DGTX:1c83": "(AUTO) duplicate key", "erc20:eth:DGTX:c666": "(AUTO) duplicate key", "erc20:eth:DOW:7697": "(AUTO) duplicate key", @@ -2319,6 +2343,8 @@ "erc20:eth:GANA:c0ea": "(AUTO) duplicate key", "erc20:eth:GMT:7ddc": "(AUTO) duplicate key", "erc20:eth:GMT:b3bd": "(AUTO) duplicate key", + "erc20:eth:GNT": "(AUTO) duplicate key", + "erc20:eth:GUP": "(AUTO) duplicate key", "erc20:eth:HEX:9600": "(AUTO) duplicate key", "erc20:eth:Hdp": "(AUTO) duplicate key", "erc20:eth:Hdp.\u0444": "(AUTO) duplicate key", @@ -2330,6 +2356,7 @@ "erc20:eth:JET:7734": "(AUTO) duplicate key", "erc20:eth:JET:8727": "(AUTO) duplicate key", "erc20:eth:JOB:1728": "(AUTO) duplicate key", + "erc20:eth:KC": "(AUTO) duplicate key", "erc20:eth:KEY:4cc1": "(AUTO) duplicate key", "erc20:eth:KEY:4cd9": "(AUTO) duplicate key", "erc20:eth:KICK:2769": "(AUTO) duplicate key", @@ -2356,6 +2383,9 @@ "erc20:eth:MESH:f030": "(AUTO) duplicate key", "erc20:eth:MIT": "(AUTO) duplicate key", "erc20:eth:MIT (Mychatcoin)": "(AUTO) duplicate key", + "erc20:eth:MKR": "(AUTO) duplicate key", + "erc20:eth:MLN (new)": "(AUTO) duplicate key", + "erc20:eth:MLN (old)": "(AUTO) duplicate key", "erc20:eth:MOC": "(AUTO) duplicate key", "erc20:eth:MTC:195f": "(AUTO) duplicate key", "erc20:eth:MTC:905e": "(AUTO) duplicate key", @@ -2365,6 +2395,7 @@ "erc20:eth:NCC:9344": "(AUTO) duplicate key", "erc20:eth:NIO:5554": "(AUTO) duplicate key", "erc20:eth:NIO:cc2a": "(AUTO) duplicate key", + "erc20:eth:NONE": "(AUTO) duplicate key", "erc20:eth:NTK:5d4d": "(AUTO) duplicate key", "erc20:eth:NTK:69be": "(AUTO) duplicate key", "erc20:eth:NXX OLD": "(AUTO) duplicate key", @@ -2389,8 +2420,12 @@ "erc20:eth:QBIT (Old)": "(AUTO) duplicate key", "erc20:eth:RCT:13f2": "(AUTO) duplicate key", "erc20:eth:RCT:2a3a": "(AUTO) duplicate key", + "erc20:eth:RDN": "(AUTO) duplicate key", + "erc20:eth:REP:1985": "(AUTO) duplicate key", + "erc20:eth:REP:e943": "(AUTO) duplicate key", "erc20:eth:RING:86e5": "(AUTO) duplicate key", "erc20:eth:RING:9469": "(AUTO) duplicate key", + "erc20:eth:RLC": "(AUTO) duplicate key", "erc20:eth:SGT:3742": "(AUTO) duplicate key", "erc20:eth:SGT:616c": "(AUTO) duplicate key", "erc20:eth:SGT:d248": "(AUTO) duplicate key", @@ -2438,6 +2473,7 @@ "erc20:eth:YUP:0f33": "(AUTO) duplicate key", "erc20:eth:YUP:d9a1": "(AUTO) duplicate key", "erc20:eth:ZIL": "Migrated to mainnet", + "erc20:eth:ZRX": "(AUTO) duplicate key", "erc20:eth:aDAI:363e": "(AUTO) duplicate key", "erc20:eth:aDAI:5dc2": "(AUTO) duplicate key", "erc20:eth:aDAI:fc1e": "(AUTO) duplicate key", @@ -2469,20 +2505,43 @@ "erc20:eth:univ2FARMUSDC:0d0d": "(AUTO) duplicate key", "erc20:eth:univ2FARMUSDC:5149": "(AUTO) duplicate key", "erc20:gor:TST": "(AUTO) duplicate key", + "erc20:kov:DAI": "(AUTO) duplicate key", + "erc20:kov:DGD": "(AUTO) duplicate key", + "erc20:kov:GNT": "(AUTO) duplicate key", + "erc20:kov:GUP": "(AUTO) duplicate key", + "erc20:kov:MKR:1dad": "(AUTO) duplicate key", + "erc20:kov:MKR:aaf6": "(AUTO) duplicate key", + "erc20:kov:MLN": "(AUTO) duplicate key", + "erc20:kov:REP": "(AUTO) duplicate key", + "erc20:kov:RLC": "(AUTO) duplicate key", + "erc20:kov:ZRX": "(AUTO) duplicate key", "erc20:rin:AETH": "(AUTO) duplicate key", + "erc20:rin:KC": "(AUTO) duplicate key", + "erc20:rin:NONE": "(AUTO) duplicate key", + "erc20:rin:RDN": "(AUTO) duplicate key", + "erc20:rin:RLC": "(AUTO) duplicate key", + "erc20:rop:NONE": "(AUTO) duplicate key", + "erc20:rop:RLC": "(AUTO) duplicate key", "erc20:rsk:INV": "(AUTO) duplicate key", "erc20:rsk:MOC": "(AUTO) duplicate key", - "eth:AETH": "duplicate key", "eth:ATH:1620": "duplicate key", "eth:ATH:43110": "duplicate key", "eth:BCH": "duplicate of bitcoin:BCH", "eth:BTX": "duplicate key", "eth:ELA:22": "duplicate of ELA-ETH-sidechain", "eth:EOS": "mainnet exists", + "eth:ETH:10": "duplicate key", + "eth:ETH:1313161554": "duplicate key", + "eth:ETH:1313161556": "duplicate key", "eth:ETH:288": "duplicate key", + "eth:ETH:42161": "duplicate key", + "eth:GAR:91": "duplicate key", + "eth:GAR:92": "duplicate key", + "eth:GAR:93": "duplicate key", "eth:GTH:192837465": "duplicate key", "eth:GTH:356256156": "exclude testnet", "eth:GTH:486217935": "exclude testnet", + "eth:JEWEL:335": "exclude testnet", "eth:KTO:8285": "exclude testnet", "eth:NEON:245022926": "duplicate key", "eth:QKC:110000": "exclude testnet", @@ -2494,8 +2553,11 @@ "eth:QKC:110006": "exclude testnet", "eth:QKC:110007": "exclude testnet", "eth:QKC:110008": "exclude testnet", + "eth:REI:55555": "duplicate key", + "eth:SHYFT": "slip44 out of range", "eth:SYS": "duplicate key", "eth:TCRO": "(AUTO) exclude testnet", + "eth:TELE:8001": "(AUTO) exclude testnet", "eth:TFUEL:361": "incompatible", "eth:TFUEL:363": "(AUTO) exclude testnet", "eth:TFUEL:364": "(AUTO) exclude testnet", @@ -2508,37 +2570,56 @@ "eth:TKM:70001": "duplicate key", "eth:TKM:70002": "duplicate key", "eth:TKM:70103": "duplicate key", + "eth:TLA": "(AUTO) exclude testnet", "eth:TLOS:41": "(AUTO) exclude testnet", + "eth:TOMO:89": "(AUTO) exclude testnet", "eth:TSCAS": "(AUTO) exclude testnet", - "eth:aETH:1313161556": "exclude testnet", + "eth:VS:666666": "exclude testnet", + "eth:W3Q:3334": "duplicate key", + "eth:tAAC": "(AUTO) exclude testnet", "eth:tAMBR": "(AUTO) exclude testnet", "eth:tARETH": "(AUTO) exclude testnet", + "eth:tAVIS": "(AUTO) exclude testnet", "eth:tBCHT": "(AUTO) exclude testnet", + "eth:tBCS": "(AUTO) exclude testnet", "eth:tBTM": "(AUTO) exclude testnet", "eth:tBTT": "(AUTO) exclude testnet", - "eth:tCKB": "(AUTO) exclude testnet", + "eth:tCFX": "(AUTO) exclude testnet", + "eth:tCKB:71393": "(AUTO) exclude testnet", + "eth:tCKB:868455272153094": "(AUTO) exclude testnet", "eth:tCLV": "(AUTO) exclude testnet", "eth:tDTH": "(AUTO) exclude testnet", + "eth:tDYNO": "(AUTO) exclude testnet", "eth:tECO": "(AUTO) exclude testnet", + "eth:tECS": "(AUTO) exclude testnet", "eth:tEDG": "(AUTO) exclude testnet", "eth:tELA:21": "(AUTO) exclude testnet", "eth:tELA:23": "(AUTO) exclude testnet", "eth:tEOS": "(AUTO) exclude testnet", - "eth:tETH": "(AUTO) exclude testnet", + "eth:tETH:1313161555": "(AUTO) exclude testnet", + "eth:tETH:28": "(AUTO) exclude testnet", + "eth:tEVMOS": "(AUTO) exclude testnet", "eth:tFETH": "(AUTO) exclude testnet", "eth:tFTM": "(AUTO) exclude testnet", + "eth:tGAR:900": "(AUTO) exclude testnet", + "eth:tGAR:901": "(AUTO) exclude testnet", + "eth:tGAR:902": "(AUTO) exclude testnet", + "eth:tGAR:903": "(AUTO) exclude testnet", "eth:tGO": "(AUTO) exclude testnet", "eth:tGT": "(AUTO) exclude testnet", "eth:tGooD": "(AUTO) exclude testnet", "eth:tHOO": "(AUTO) exclude testnet", + "eth:tHYM": "(AUTO) exclude testnet", "eth:tIOTX": "(AUTO) exclude testnet", "eth:tKCS": "(AUTO) exclude testnet", "eth:tL1test": "(AUTO) exclude testnet", "eth:tMDGLT": "(AUTO) exclude testnet", + "eth:tMESHT": "(AUTO) exclude testnet", "eth:tMETIS": "(AUTO) exclude testnet", "eth:tMTR": "(AUTO) exclude testnet", "eth:tMTT-test": "(AUTO) exclude testnet", "eth:tMYN": "(AUTO) exclude testnet", + "eth:tNBX": "(AUTO) exclude testnet", "eth:tNEON": "(AUTO) exclude testnet", "eth:tNTTH": "(AUTO) exclude testnet", "eth:tOKT": "(AUTO) exclude testnet", @@ -2549,22 +2630,31 @@ "eth:tONE:1666700002": "(AUTO) exclude testnet", "eth:tONE:1666700003": "(AUTO) exclude testnet", "eth:tONG": "(AUTO) exclude testnet", + "eth:tORING": "(AUTO) exclude testnet", + "eth:tOY": "(AUTO) exclude testnet", "eth:tPALM": "(AUTO) exclude testnet", "eth:tPCTT": "(AUTO) exclude testnet", - "eth:tPHOTON": "(AUTO) exclude testnet", - "eth:tPLS": "(AUTO) exclude testnet", + "eth:tPLS:940": "(AUTO) exclude testnet", + "eth:tPLS:941": "(AUTO) exclude testnet", + "eth:tPLS:942": "(AUTO) exclude testnet", "eth:tPOLIS": "(AUTO) exclude testnet", + "eth:tPRB": "(AUTO) exclude testnet", "eth:tPRING": "(AUTO) exclude testnet", + "eth:tREI": "(AUTO) exclude testnet", "eth:tRNA": "(AUTO) exclude testnet", "eth:tROSE": "(AUTO) exclude testnet", "eth:tRPG": "(AUTO) exclude testnet", + "eth:tSHYFTT": "(AUTO) exclude testnet", "eth:tSYS": "(AUTO) exclude testnet", + "eth:tUBC": "(AUTO) exclude testnet", "eth:tW3G": "(AUTO) exclude testnet", + "eth:tW3Q": "(AUTO) exclude testnet", "eth:tWAN": "(AUTO) exclude testnet", + "eth:tWLK": "(AUTO) exclude testnet", "eth:tXPR": "(AUTO) exclude testnet", + "eth:tXVM": "(AUTO) exclude testnet", "eth:tZCR": "(AUTO) exclude testnet", "eth:tZERO": "(AUTO) exclude testnet", - "eth:taETH": "(AUTO) exclude testnet", "eth:tatp": "(AUTO) exclude testnet", "eth:tcett": "(AUTO) exclude testnet", "eth:tkiETH": "(AUTO) exclude testnet", @@ -2681,6 +2771,7 @@ "erc20:eth:AEUR": "2.3.0", "erc20:eth:AFA": "2.0.10", "erc20:eth:AGI": "2.0.7", + "erc20:eth:AGRS": "2.4.4", "erc20:eth:AGS": "2.3.0", "erc20:eth:AI": "2.0.10", "erc20:eth:AID": "2.0.10", @@ -2692,6 +2783,7 @@ "erc20:eth:ALEPH": "2.3.7", "erc20:eth:ALI": "2.0.10", "erc20:eth:ALIS": "2.0.7", + "erc20:eth:ALTA": "2.4.4", "erc20:eth:ALTS": "2.0.7", "erc20:eth:ALX": "2.0.10", "erc20:eth:AMB": "2.0.7", @@ -2887,7 +2979,6 @@ "erc20:eth:CHP": "2.0.10", "erc20:eth:CHSB": "2.0.7", "erc20:eth:CHX": "2.0.10", - "erc20:eth:CIG": "2.3.0", "erc20:eth:CIV": "2.4.4", "erc20:eth:CIYA": "2.0.11", "erc20:eth:CJT": "2.0.10", @@ -2904,6 +2995,7 @@ "erc20:eth:CMERGE": "2.4.4", "erc20:eth:CNB": "2.0.7", "erc20:eth:CND": "2.0.7", + "erc20:eth:CNDL": "2.4.4", "erc20:eth:CNN": "2.0.10", "erc20:eth:CO2": "2.0.7", "erc20:eth:CO2Bit": "2.0.7", @@ -2959,7 +3051,7 @@ "erc20:eth:DAB": "2.0.7", "erc20:eth:DACS": "2.0.10", "erc20:eth:DADI": "2.0.7", - "erc20:eth:DAI": "2.0.10", + "erc20:eth:DAF": "2.4.4", "erc20:eth:DALC": "2.0.7", "erc20:eth:DAN": "2.0.7", "erc20:eth:DAT": "2.0.7", @@ -2984,7 +3076,6 @@ "erc20:eth:DEW": "2.0.10", "erc20:eth:DEX": "2.0.10", "erc20:eth:DF": "2.3.0", - "erc20:eth:DGD": "2.0.10", "erc20:eth:DGPT": "2.0.7", "erc20:eth:DGS": "2.0.8", "erc20:eth:DGX": "2.0.7", @@ -3178,7 +3269,6 @@ "erc20:eth:GL": "2.3.1", "erc20:eth:GLA": "2.0.10", "erc20:eth:GNO": "2.0.7", - "erc20:eth:GNT": "2.0.10", "erc20:eth:GNX": "2.0.10", "erc20:eth:GNY": "2.0.10", "erc20:eth:GOLDX": "2.0.7", @@ -3199,7 +3289,6 @@ "erc20:eth:GTO": "2.0.7", "erc20:eth:GUESS": "2.0.10", "erc20:eth:GULD": "2.0.8", - "erc20:eth:GUP": "2.0.10", "erc20:eth:GUSD": "2.0.11", "erc20:eth:GVT": "2.0.7", "erc20:eth:GXC": "2.0.7", @@ -3306,7 +3395,6 @@ "erc20:eth:JSE": "2.3.0", "erc20:eth:KAN": "2.0.10", "erc20:eth:KAPA": "2.1.8", - "erc20:eth:KC": "2.0.10", "erc20:eth:KCS": "2.3.0", "erc20:eth:KEE": "2.0.7", "erc20:eth:KIN": "2.0.7", @@ -3367,6 +3455,7 @@ "erc20:eth:LRC": "2.0.7", "erc20:eth:LRC (old):deprecated": "2.3.0", "erc20:eth:LUC": "2.0.7", + "erc20:eth:LUCHOW": "2.4.4", "erc20:eth:LUCK": "2.0.7", "erc20:eth:LULU": "2.3.0", "erc20:eth:LUM": "2.0.7", @@ -3388,6 +3477,7 @@ "erc20:eth:MDA": "2.0.7", "erc20:eth:MDT": "2.0.10", "erc20:eth:MDX": "2.3.7", + "erc20:eth:MEDCASH": "2.4.4", "erc20:eth:MEDX": "2.0.10", "erc20:eth:MEME": "2.3.7", "erc20:eth:MESG": "2.1.8", @@ -3405,10 +3495,7 @@ "erc20:eth:MINDS": "2.4.2", "erc20:eth:MITH": "2.3.0", "erc20:eth:MITX": "2.0.11", - "erc20:eth:MKR": "2.0.10", "erc20:eth:MKT": "2.0.7", - "erc20:eth:MLN (new)": "2.0.11", - "erc20:eth:MLN (old):deprecated": "2.0.11", "erc20:eth:MM": "2.4.3", "erc20:eth:MNE": "2.0.7", "erc20:eth:MNL": "2.3.7", @@ -3467,7 +3554,6 @@ "erc20:eth:NMR": "2.0.7", "erc20:eth:NOAH": "2.0.10", "erc20:eth:NOBS": "2.0.10", - "erc20:eth:NONE": "2.0.10", "erc20:eth:NOT": "2.3.0", "erc20:eth:NOX": "2.0.7", "erc20:eth:NPER": "2.0.7", @@ -3629,7 +3715,6 @@ "erc20:eth:RBT": "2.3.3", "erc20:eth:RBX": "2.4.4", "erc20:eth:RCN": "2.0.7", - "erc20:eth:RDN": "2.0.10", "erc20:eth:RDV": "2.3.0", "erc20:eth:REA": "2.0.7", "erc20:eth:REAL": "2.0.10", @@ -3641,8 +3726,6 @@ "erc20:eth:REM": "2.0.10", "erc20:eth:REMI": "2.0.11", "erc20:eth:REN": "2.0.7", - "erc20:eth:REP": "2.0.10", - "erc20:eth:REP:deprecated": "2.0.10", "erc20:eth:REPv2": "2.3.5", "erc20:eth:REQ": "2.0.7", "erc20:eth:RET": "2.3.0", @@ -3655,7 +3738,6 @@ "erc20:eth:RIPT": "2.0.7", "erc20:eth:RIYA": "2.0.10", "erc20:eth:RKT": "2.0.10", - "erc20:eth:RLC": "2.0.7", "erc20:eth:RLT": "2.0.7", "erc20:eth:RLTY": "2.0.7", "erc20:eth:RLX": "2.0.7", @@ -3673,6 +3755,7 @@ "erc20:eth:ROUND": "2.0.7", "erc20:eth:RPE": "2.1.8", "erc20:eth:RPL": "2.0.7", + "erc20:eth:RSR": "2.4.4", "erc20:eth:RTB": "2.0.10", "erc20:eth:RTC": "2.1.8", "erc20:eth:RTH": "2.0.10", @@ -3698,6 +3781,7 @@ "erc20:eth:SENT": "2.0.10", "erc20:eth:SET": "2.0.7", "erc20:eth:SETS": "2.3.7", + "erc20:eth:SEV": "2.4.4", "erc20:eth:SEXY": "2.0.7", "erc20:eth:SGA": "2.3.0", "erc20:eth:SGEL": "2.0.7", @@ -3796,6 +3880,7 @@ "erc20:eth:SXR": "2.3.0", "erc20:eth:SXUT": "2.0.7", "erc20:eth:SYN": "2.0.7", + "erc20:eth:SYS": "2.4.4", "erc20:eth:SYSX": "2.3.7", "erc20:eth:SenSatorI": "2.0.7", "erc20:eth:TALAO": "2.0.10", @@ -3951,6 +4036,8 @@ "erc20:eth:WIN": "2.0.10", "erc20:eth:WINGS": "2.0.7", "erc20:eth:WISH": "2.0.10", + "erc20:eth:WLKR": "2.4.4", + "erc20:eth:WLKRR": "2.4.4", "erc20:eth:WMA": "2.4.2", "erc20:eth:WMK": "2.0.8", "erc20:eth:WNK": "2.0.8", @@ -4024,7 +4111,6 @@ "erc20:eth:ZMAN": "2.1.8", "erc20:eth:ZMN": "2.0.7", "erc20:eth:ZPR": "2.0.10", - "erc20:eth:ZRX": "2.0.10", "erc20:eth:ZST": "2.0.7", "erc20:eth:ZTX": "2.0.10", "erc20:eth:ZXC": "2.0.10", @@ -4424,32 +4510,17 @@ "erc20:eth:xOXT": "2.3.0", "erc20:eth:xSOL": "2.3.0", "erc20:kov:Aeternity": "2.0.7", - "erc20:kov:DAI": "2.0.10", - "erc20:kov:DGD": "2.0.10", "erc20:kov:GAV": "2.3.0", - "erc20:kov:GNT": "2.0.10", - "erc20:kov:GUP": "2.0.10", - "erc20:kov:MKR:1dad": "2.3.0", - "erc20:kov:MKR:aaf6": "2.3.0", - "erc20:kov:MLN": "2.0.10", - "erc20:kov:REP": "2.0.10", - "erc20:kov:RLC": "2.3.0", "erc20:kov:TIB": "2.3.0", - "erc20:kov:ZRX": "2.0.10", "erc20:rin:BHNT": "2.0.7", "erc20:rin:CTGA": "2.0.7", - "erc20:rin:KC": "2.0.10", - "erc20:rin:NONE": "2.0.10", "erc20:rin:PPD": "2.0.7", - "erc20:rin:RDN": "2.0.10", - "erc20:rin:RLC": "2.3.0", "erc20:rin:WALL": "2.0.7", "erc20:rin:qwe": "2.3.0", "erc20:rop:*PLASMA": "2.0.8", "erc20:rop:ILSC": "2.0.7", "erc20:rop:MEWV5": "2.3.0", - "erc20:rop:NONE": "2.0.10", - "erc20:rop:RLC": "2.3.0", + "erc20:rop:RCL": "2.4.4", "erc20:rop:dqr30": "2.0.10", "erc20:rsk:ARSCB": "2.4.3", "erc20:rsk:BOBCB": "2.4.3", @@ -4492,11 +4563,20 @@ "erc20:ubq:BEER": "2.0.7", "erc20:ubq:CEFS": "2.0.7", "erc20:ubq:DOT": "2.0.7", + "erc20:ubq:ESCH": "2.4.4", + "erc20:ubq:GEO": "2.4.4", + "erc20:ubq:GRANS": "2.4.4", + "erc20:ubq:INK": "2.4.4", "erc20:ubq:QWARK": "2.0.7", "erc20:ubq:RICKS": "2.0.7", + "erc20:ubq:SNARG": "2.4.4", + "erc20:ubq:SPHR": "2.4.4", + "erc20:ubq:SPHRC": "2.4.4", + "erc20:ubq:TGE1": "2.4.4", "eth:$OC": "2.4.4", "eth:0xF": "2.3.5", "eth:420": "2.3.7", + "eth:AAC": "2.4.4", "eth:ACA": "2.3.7", "eth:AKA": "2.0.8", "eth:AMBR": "2.4.3", @@ -4505,13 +4585,19 @@ "eth:ATS": "2.0.11", "eth:AUX": "2.1.6", "eth:AVAX": "2.3.7", + "eth:BCS": "2.4.4", "eth:BNB": "2.3.5", + "eth:BOY": "2.4.4", + "eth:BRO": "2.4.4", "eth:BTA": "2.4.3", "eth:BTCIX": "2.4.4", "eth:BTM": "2.4.4", "eth:BTT": "2.4.3", "eth:CATE": "2.4.2", + "eth:CCP": "2.4.4", "eth:CELO": "2.3.7", + "eth:CFX": "2.4.4", + "eth:CLASS": "2.4.4", "eth:CLO": "2.0.7", "eth:CLV": "2.4.2", "eth:CRAB": "2.4.4", @@ -4519,13 +4605,18 @@ "eth:DAX": "2.4.2", "eth:DEV": "2.4.3", "eth:DIODE": "2.3.7", + "eth:DTH": "2.4.4", "eth:DWU": "2.4.2", + "eth:DYNO": "2.4.4", "eth:ECO": "2.4.3", + "eth:ECS": "2.4.4", "eth:EDG": "2.4.2", "eth:EGEM": "2.0.7", + "eth:EIDI": "2.4.4", "eth:ELA:20": "2.4.2", "eth:ELLA": "2.0.7", "eth:ELV": "2.4.3", + "eth:ENTER": "2.4.4", "eth:ES": "2.4.2", "eth:ESN": "2.0.8", "eth:ETC": "2.0.7", @@ -4533,7 +4624,9 @@ "eth:ETHO": "2.0.8", "eth:ETI": "2.1.1", "eth:ETL": "2.4.2", + "eth:EVA": "2.4.4", "eth:EVC": "2.4.2", + "eth:EVMOS": "2.4.4", "eth:EWT": "2.3.5", "eth:EXP": "2.0.7", "eth:FETH": "2.4.2", @@ -4542,8 +4635,10 @@ "eth:FSN": "2.4.2", "eth:FTM": "2.3.5", "eth:FUSE": "2.3.5", + "eth:GAR:90": "2.4.4", "eth:GEN": "2.4.2", "eth:GLMR": "2.4.2", + "eth:GNC": "2.4.4", "eth:GO": "2.0.7", "eth:GT": "2.4.2", "eth:GooD": "2.4.2", @@ -4553,8 +4648,10 @@ "eth:HPB": "2.1.1", "eth:HT": "2.3.7", "eth:ILT": "2.3.5", + "eth:IORA": "2.4.4", "eth:IOTX": "2.4.2", "eth:IPOS": "2.3.5", + "eth:JEWEL:53935": "2.4.4", "eth:JOYS": "2.3.7", "eth:KAR": "2.3.7", "eth:KCS": "2.4.2", @@ -4562,6 +4659,7 @@ "eth:KTO:2559": "2.4.2", "eth:L1": "2.4.4", "eth:L99": "2.4.3", + "eth:LA": "2.4.4", "eth:LISINSKI": "2.3.5", "eth:MATH": "2.3.7", "eth:MATIC": "2.3.5", @@ -4571,7 +4669,6 @@ "eth:MIX": "2.0.10", "eth:MOLE": "2.4.4", "eth:MOVR": "2.4.2", - "eth:MSHD": "2.4.2", "eth:MTR": "2.3.7", "eth:MTT": "2.4.2", "eth:MUSIC": "2.0.8", @@ -4580,24 +4677,27 @@ "eth:NEXT": "2.4.4", "eth:NRG": "2.3.5", "eth:NTT": "2.4.4", - "eth:OETH": "2.3.5", "eth:OKT": "2.3.7", "eth:OLO": "2.4.2", "eth:OLT": "2.4.3", + "eth:OML": "2.4.4", "eth:ONE:1666600000": "2.3.7", "eth:ONE:1666600001": "2.3.7", "eth:ONE:1666600002": "2.3.7", "eth:ONE:1666600003": "2.3.7", "eth:ONG": "2.4.2", + "eth:OY": "2.4.4", "eth:PALM": "2.4.3", "eth:PETH": "2.4.2", "eth:PHT": "2.3.5", + "eth:PHX": "2.4.4", "eth:PIRL": "2.0.8", "eth:PIX": "2.4.4", "eth:PLS": "2.4.3", "eth:POA": "2.3.5", "eth:POLIS": "2.4.4", "eth:POP": "2.4.3", + "eth:PRB": "2.4.4", "eth:QKC:100000": "2.4.2", "eth:QKC:100001": "2.4.2", "eth:QKC:100002": "2.4.2", @@ -4610,15 +4710,18 @@ "eth:QKI": "2.4.2", "eth:RBD": "2.3.5", "eth:RBTC": "2.0.7", + "eth:REI:47805": "2.4.4", "eth:RNA": "2.4.2", "eth:ROC": "2.4.2", "eth:ROSE": "2.4.4", "eth:RPG": "2.4.4", "eth:RUPX": "2.3.7", "eth:SDN": "2.4.3", + "eth:SETM": "2.4.4", "eth:SGB": "2.4.2", "eth:SHIB": "2.4.4", "eth:SKU": "2.4.2", + "eth:SNT": "2.4.4", "eth:SOTER": "2.3.7", "eth:SPARK": "2.4.4", "eth:SPOA": "2.4.4", @@ -4628,10 +4731,11 @@ "eth:TBG": "2.3.7", "eth:TCH": "2.3.5", "eth:TCLO": "2.3.5", + "eth:TELE:8000": "2.4.4", "eth:TETC": "2.3.5", "eth:TFI": "2.3.7", "eth:TLOS:40": "2.4.2", - "eth:TOMO": "2.3.5", + "eth:TOMO:88": "2.4.4", "eth:TOYS": "2.3.7", "eth:TPEP": "2.3.5", "eth:TSF": "2.3.5", @@ -4640,22 +4744,27 @@ "eth:TUBQ": "2.3.5", "eth:TXDC": "2.3.7", "eth:U+25B3": "2.3.5", + "eth:UBC": "2.4.4", "eth:UBQ": "2.0.7", "eth:UZMI": "2.4.4", "eth:VAL": "2.3.5", "eth:VLX": "2.4.3", + "eth:VS:888888": "2.4.4", + "eth:W3G": "2.4.4", + "eth:W3Q:333": "2.4.4", "eth:WAN": "2.4.2", "eth:WEB": "2.3.5", + "eth:WGM": "2.4.4", "eth:WTT": "2.4.4", "eth:XDC": "2.3.7", "eth:XERO": "2.3.5", "eth:YETI": "2.3.5", "eth:ZERO": "2.4.4", "eth:ZYX": "2.4.3", - "eth:aETH:1313161554": "2.4.2", "eth:atp": "2.4.4", "eth:cTH": "2.4.2", "eth:cet": "2.4.2", + "eth:lat": "2.4.4", "eth:peggle": "2.3.7", "eth:tATS": "2.0.11", "eth:tAVAX": "2.3.7", @@ -4680,6 +4789,7 @@ "eth:tRBTC": "2.0.7", "eth:tRIN": "2.0.7", "eth:tROP": "2.0.7", + "eth:tSEP": "2.4.4", "eth:tVT": "2.3.5", "eth:thtt": "2.3.7", "eth:tmACA": "2.3.7", @@ -4751,6 +4861,8 @@ "erc20:eth:CCS:315c": "(AUTO) duplicate key", "erc20:eth:CDX:2cb1": "(AUTO) duplicate key", "erc20:eth:CDX:6fff": "(AUTO) duplicate key", + "erc20:eth:CIG:0038": "(AUTO) duplicate key", + "erc20:eth:CIG:cb56": "(AUTO) duplicate key", "erc20:eth:CMT": "Migrated to mainnet", "erc20:eth:COIN:5e8f": "(AUTO) duplicate key", "erc20:eth:COIN:eb54": "(AUTO) duplicate key", @@ -4762,12 +4874,14 @@ "erc20:eth:CRPT:80a7": "(AUTO) duplicate key", "erc20:eth:CTT:1a47": "(AUTO) duplicate key", "erc20:eth:CTT:e3fa": "(AUTO) duplicate key", + "erc20:eth:DAI": "(AUTO) duplicate key", "erc20:eth:DAO:0f51": "(AUTO) duplicate key", "erc20:eth:DAO:bb9b": "(AUTO) duplicate key", "erc20:eth:DATA:0cf0": "(AUTO) duplicate key", "erc20:eth:DATA:8f69": "(AUTO) duplicate key", "erc20:eth:DEPO": "(AUTO) duplicate key", "erc20:eth:DEPO (Depository Network)": "(AUTO) duplicate key", + "erc20:eth:DGD": "(AUTO) duplicate key", "erc20:eth:DGTX:1c83": "(AUTO) duplicate key", "erc20:eth:DGTX:c666": "(AUTO) duplicate key", "erc20:eth:DOW:7697": "(AUTO) duplicate key", @@ -4806,6 +4920,8 @@ "erc20:eth:GANA:c0ea": "(AUTO) duplicate key", "erc20:eth:GMT:7ddc": "(AUTO) duplicate key", "erc20:eth:GMT:b3bd": "(AUTO) duplicate key", + "erc20:eth:GNT": "(AUTO) duplicate key", + "erc20:eth:GUP": "(AUTO) duplicate key", "erc20:eth:HEX:9600": "(AUTO) duplicate key", "erc20:eth:Hdp": "(AUTO) duplicate key", "erc20:eth:Hdp.\u0444": "(AUTO) duplicate key", @@ -4817,6 +4933,7 @@ "erc20:eth:JET:7734": "(AUTO) duplicate key", "erc20:eth:JET:8727": "(AUTO) duplicate key", "erc20:eth:JOB:1728": "(AUTO) duplicate key", + "erc20:eth:KC": "(AUTO) duplicate key", "erc20:eth:KEY:4cc1": "(AUTO) duplicate key", "erc20:eth:KEY:4cd9": "(AUTO) duplicate key", "erc20:eth:KICK:2769": "(AUTO) duplicate key", @@ -4843,6 +4960,9 @@ "erc20:eth:MESH:f030": "(AUTO) duplicate key", "erc20:eth:MIT": "(AUTO) duplicate key", "erc20:eth:MIT (Mychatcoin)": "(AUTO) duplicate key", + "erc20:eth:MKR": "(AUTO) duplicate key", + "erc20:eth:MLN (new)": "(AUTO) duplicate key", + "erc20:eth:MLN (old)": "(AUTO) duplicate key", "erc20:eth:MOC": "(AUTO) duplicate key", "erc20:eth:MTC:195f": "(AUTO) duplicate key", "erc20:eth:MTC:905e": "(AUTO) duplicate key", @@ -4852,6 +4972,7 @@ "erc20:eth:NCC:9344": "(AUTO) duplicate key", "erc20:eth:NIO:5554": "(AUTO) duplicate key", "erc20:eth:NIO:cc2a": "(AUTO) duplicate key", + "erc20:eth:NONE": "(AUTO) duplicate key", "erc20:eth:NTK:5d4d": "(AUTO) duplicate key", "erc20:eth:NTK:69be": "(AUTO) duplicate key", "erc20:eth:NXX OLD": "(AUTO) duplicate key", @@ -4876,8 +4997,12 @@ "erc20:eth:QBIT (Old)": "(AUTO) duplicate key", "erc20:eth:RCT:13f2": "(AUTO) duplicate key", "erc20:eth:RCT:2a3a": "(AUTO) duplicate key", + "erc20:eth:RDN": "(AUTO) duplicate key", + "erc20:eth:REP:1985": "(AUTO) duplicate key", + "erc20:eth:REP:e943": "(AUTO) duplicate key", "erc20:eth:RING:86e5": "(AUTO) duplicate key", "erc20:eth:RING:9469": "(AUTO) duplicate key", + "erc20:eth:RLC": "(AUTO) duplicate key", "erc20:eth:SGT:3742": "(AUTO) duplicate key", "erc20:eth:SGT:616c": "(AUTO) duplicate key", "erc20:eth:SGT:d248": "(AUTO) duplicate key", @@ -4925,6 +5050,7 @@ "erc20:eth:YUP:0f33": "(AUTO) duplicate key", "erc20:eth:YUP:d9a1": "(AUTO) duplicate key", "erc20:eth:ZIL": "Migrated to mainnet", + "erc20:eth:ZRX": "(AUTO) duplicate key", "erc20:eth:aDAI:363e": "(AUTO) duplicate key", "erc20:eth:aDAI:5dc2": "(AUTO) duplicate key", "erc20:eth:aDAI:fc1e": "(AUTO) duplicate key", @@ -4956,20 +5082,43 @@ "erc20:eth:univ2FARMUSDC:0d0d": "(AUTO) duplicate key", "erc20:eth:univ2FARMUSDC:5149": "(AUTO) duplicate key", "erc20:gor:TST": "(AUTO) duplicate key", + "erc20:kov:DAI": "(AUTO) duplicate key", + "erc20:kov:DGD": "(AUTO) duplicate key", + "erc20:kov:GNT": "(AUTO) duplicate key", + "erc20:kov:GUP": "(AUTO) duplicate key", + "erc20:kov:MKR:1dad": "(AUTO) duplicate key", + "erc20:kov:MKR:aaf6": "(AUTO) duplicate key", + "erc20:kov:MLN": "(AUTO) duplicate key", + "erc20:kov:REP": "(AUTO) duplicate key", + "erc20:kov:RLC": "(AUTO) duplicate key", + "erc20:kov:ZRX": "(AUTO) duplicate key", "erc20:rin:AETH": "(AUTO) duplicate key", + "erc20:rin:KC": "(AUTO) duplicate key", + "erc20:rin:NONE": "(AUTO) duplicate key", + "erc20:rin:RDN": "(AUTO) duplicate key", + "erc20:rin:RLC": "(AUTO) duplicate key", + "erc20:rop:NONE": "(AUTO) duplicate key", + "erc20:rop:RLC": "(AUTO) duplicate key", "erc20:rsk:INV": "(AUTO) duplicate key", "erc20:rsk:MOC": "(AUTO) duplicate key", - "eth:AETH": "duplicate key", "eth:ATH:1620": "duplicate key", "eth:ATH:43110": "duplicate key", "eth:BCH": "duplicate of bitcoin:BCH", "eth:BTX": "duplicate key", "eth:ELA:22": "duplicate of ELA-ETH-sidechain", "eth:EOS": "mainnet exists", + "eth:ETH:10": "duplicate key", + "eth:ETH:1313161554": "duplicate key", + "eth:ETH:1313161556": "duplicate key", "eth:ETH:288": "duplicate key", + "eth:ETH:42161": "duplicate key", + "eth:GAR:91": "duplicate key", + "eth:GAR:92": "duplicate key", + "eth:GAR:93": "duplicate key", "eth:GTH:192837465": "duplicate key", "eth:GTH:356256156": "exclude testnet", "eth:GTH:486217935": "exclude testnet", + "eth:JEWEL:335": "exclude testnet", "eth:KTO:8285": "exclude testnet", "eth:NEON:245022926": "duplicate key", "eth:QKC:110000": "exclude testnet", @@ -4981,8 +5130,11 @@ "eth:QKC:110006": "exclude testnet", "eth:QKC:110007": "exclude testnet", "eth:QKC:110008": "exclude testnet", + "eth:REI:55555": "duplicate key", + "eth:SHYFT": "slip44 out of range", "eth:SYS": "duplicate key", "eth:TCRO": "(AUTO) exclude testnet", + "eth:TELE:8001": "(AUTO) exclude testnet", "eth:TFUEL:361": "incompatible", "eth:TFUEL:363": "(AUTO) exclude testnet", "eth:TFUEL:364": "(AUTO) exclude testnet", @@ -4995,37 +5147,56 @@ "eth:TKM:70001": "duplicate key", "eth:TKM:70002": "duplicate key", "eth:TKM:70103": "duplicate key", + "eth:TLA": "(AUTO) exclude testnet", "eth:TLOS:41": "(AUTO) exclude testnet", + "eth:TOMO:89": "(AUTO) exclude testnet", "eth:TSCAS": "(AUTO) exclude testnet", - "eth:aETH:1313161556": "exclude testnet", + "eth:VS:666666": "exclude testnet", + "eth:W3Q:3334": "duplicate key", + "eth:tAAC": "(AUTO) exclude testnet", "eth:tAMBR": "(AUTO) exclude testnet", "eth:tARETH": "(AUTO) exclude testnet", + "eth:tAVIS": "(AUTO) exclude testnet", "eth:tBCHT": "(AUTO) exclude testnet", + "eth:tBCS": "(AUTO) exclude testnet", "eth:tBTM": "(AUTO) exclude testnet", "eth:tBTT": "(AUTO) exclude testnet", - "eth:tCKB": "(AUTO) exclude testnet", + "eth:tCFX": "(AUTO) exclude testnet", + "eth:tCKB:71393": "(AUTO) exclude testnet", + "eth:tCKB:868455272153094": "(AUTO) exclude testnet", "eth:tCLV": "(AUTO) exclude testnet", "eth:tDTH": "(AUTO) exclude testnet", + "eth:tDYNO": "(AUTO) exclude testnet", "eth:tECO": "(AUTO) exclude testnet", + "eth:tECS": "(AUTO) exclude testnet", "eth:tEDG": "(AUTO) exclude testnet", "eth:tELA:21": "(AUTO) exclude testnet", "eth:tELA:23": "(AUTO) exclude testnet", "eth:tEOS": "(AUTO) exclude testnet", - "eth:tETH": "(AUTO) exclude testnet", + "eth:tETH:1313161555": "(AUTO) exclude testnet", + "eth:tETH:28": "(AUTO) exclude testnet", + "eth:tEVMOS": "(AUTO) exclude testnet", "eth:tFETH": "(AUTO) exclude testnet", "eth:tFTM": "(AUTO) exclude testnet", + "eth:tGAR:900": "(AUTO) exclude testnet", + "eth:tGAR:901": "(AUTO) exclude testnet", + "eth:tGAR:902": "(AUTO) exclude testnet", + "eth:tGAR:903": "(AUTO) exclude testnet", "eth:tGO": "(AUTO) exclude testnet", "eth:tGT": "(AUTO) exclude testnet", "eth:tGooD": "(AUTO) exclude testnet", "eth:tHOO": "(AUTO) exclude testnet", + "eth:tHYM": "(AUTO) exclude testnet", "eth:tIOTX": "(AUTO) exclude testnet", "eth:tKCS": "(AUTO) exclude testnet", "eth:tL1test": "(AUTO) exclude testnet", "eth:tMDGLT": "(AUTO) exclude testnet", + "eth:tMESHT": "(AUTO) exclude testnet", "eth:tMETIS": "(AUTO) exclude testnet", "eth:tMTR": "(AUTO) exclude testnet", "eth:tMTT-test": "(AUTO) exclude testnet", "eth:tMYN": "(AUTO) exclude testnet", + "eth:tNBX": "(AUTO) exclude testnet", "eth:tNEON": "(AUTO) exclude testnet", "eth:tNTTH": "(AUTO) exclude testnet", "eth:tOKT": "(AUTO) exclude testnet", @@ -5036,22 +5207,31 @@ "eth:tONE:1666700002": "(AUTO) exclude testnet", "eth:tONE:1666700003": "(AUTO) exclude testnet", "eth:tONG": "(AUTO) exclude testnet", + "eth:tORING": "(AUTO) exclude testnet", + "eth:tOY": "(AUTO) exclude testnet", "eth:tPALM": "(AUTO) exclude testnet", "eth:tPCTT": "(AUTO) exclude testnet", - "eth:tPHOTON": "(AUTO) exclude testnet", - "eth:tPLS": "(AUTO) exclude testnet", + "eth:tPLS:940": "(AUTO) exclude testnet", + "eth:tPLS:941": "(AUTO) exclude testnet", + "eth:tPLS:942": "(AUTO) exclude testnet", "eth:tPOLIS": "(AUTO) exclude testnet", + "eth:tPRB": "(AUTO) exclude testnet", "eth:tPRING": "(AUTO) exclude testnet", + "eth:tREI": "(AUTO) exclude testnet", "eth:tRNA": "(AUTO) exclude testnet", "eth:tROSE": "(AUTO) exclude testnet", "eth:tRPG": "(AUTO) exclude testnet", + "eth:tSHYFTT": "(AUTO) exclude testnet", "eth:tSYS": "(AUTO) exclude testnet", + "eth:tUBC": "(AUTO) exclude testnet", "eth:tW3G": "(AUTO) exclude testnet", + "eth:tW3Q": "(AUTO) exclude testnet", "eth:tWAN": "(AUTO) exclude testnet", + "eth:tWLK": "(AUTO) exclude testnet", "eth:tXPR": "(AUTO) exclude testnet", + "eth:tXVM": "(AUTO) exclude testnet", "eth:tZCR": "(AUTO) exclude testnet", "eth:tZERO": "(AUTO) exclude testnet", - "eth:taETH": "(AUTO) exclude testnet", "eth:tatp": "(AUTO) exclude testnet", "eth:tcett": "(AUTO) exclude testnet", "eth:tkiETH": "(AUTO) exclude testnet", diff --git a/common/tools/coin_info.py b/common/tools/coin_info.py index 8f4e29eaa..fd2e383af 100755 --- a/common/tools/coin_info.py +++ b/common/tools/coin_info.py @@ -235,7 +235,8 @@ def _load_ethereum_networks(): chain_data = load_json(chain) shortcut = chain_data["nativeCurrency"]["symbol"] name = chain_data["name"] - is_testnet = "testnet" in name.lower() + title = chain_data.get("title", "") + is_testnet = "testnet" in name.lower() or "testnet" in title.lower() if is_testnet: slip44 = 1 else: diff --git a/core/src/apps/ethereum/networks.py b/core/src/apps/ethereum/networks.py index 3c44f368f..84be0b6cc 100644 --- a/core/src/apps/ethereum/networks.py +++ b/core/src/apps/ethereum/networks.py @@ -60,21 +60,21 @@ def _networks_iterator() -> Iterator[NetworkInfo]: chain_id=3, slip44=1, shortcut="tROP", - name="Ethereum Testnet Ropsten", + name="Ropsten", rskip60=False, ) yield NetworkInfo( chain_id=4, slip44=1, shortcut="tRIN", - name="Ethereum Testnet Rinkeby", + name="Rinkeby", rskip60=False, ) yield NetworkInfo( chain_id=5, slip44=1, shortcut="tGOR", - name="Ethereum Testnet Görli", + name="Görli", rskip60=False, ) yield NetworkInfo( @@ -105,13 +105,6 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Ubiq Network Testnet", rskip60=False, ) - yield NetworkInfo( - chain_id=10, - slip44=60, - shortcut="OETH", - name="Optimistic Ethereum", - rskip60=False, - ) yield NetworkInfo( chain_id=11, slip44=916, @@ -179,7 +172,14 @@ def _networks_iterator() -> Iterator[NetworkInfo]: chain_id=20, slip44=60, shortcut="ELA", - name="ELA-ETH-Sidechain", + name="Elastos Smart Chain", + rskip60=False, + ) + yield NetworkInfo( + chain_id=24, + slip44=60, + shortcut="DTH", + name="Dithereum", rskip60=False, ) yield NetworkInfo( @@ -249,7 +249,7 @@ def _networks_iterator() -> Iterator[NetworkInfo]: chain_id=42, slip44=1, shortcut="tKOV", - name="Ethereum Testnet Kovan", + name="Kovan", rskip60=False, ) yield NetworkInfo( @@ -340,7 +340,7 @@ def _networks_iterator() -> Iterator[NetworkInfo]: chain_id=66, slip44=60, shortcut="OKT", - name="OKExChain", + name="OKXChain", rskip60=False, ) yield NetworkInfo( @@ -361,7 +361,14 @@ def _networks_iterator() -> Iterator[NetworkInfo]: chain_id=69, slip44=1, shortcut="tKOR", - name="Optimistic Ethereum Testnet Kovan", + name="Optimism Kovan", + rskip60=False, + ) + yield NetworkInfo( + chain_id=74, + slip44=60, + shortcut="EIDI", + name="IDChain", rskip60=False, ) yield NetworkInfo( @@ -406,6 +413,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="GateChain", rskip60=False, ) + yield NetworkInfo( + chain_id=87, + slip44=60, + shortcut="SNT", + name="Nova Network", + rskip60=False, + ) yield NetworkInfo( chain_id=88, slip44=889, @@ -413,6 +427,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="TomoChain", rskip60=False, ) + yield NetworkInfo( + chain_id=90, + slip44=60, + shortcut="GAR", + name="Garizon Stage0", + rskip60=False, + ) yield NetworkInfo( chain_id=96, slip44=60, @@ -448,6 +469,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="EtherInc", rskip60=False, ) + yield NetworkInfo( + chain_id=105, + slip44=60, + shortcut="W3G", + name="Web3Games Devnet", + rskip60=False, + ) yield NetworkInfo( chain_id=106, slip44=60, @@ -490,6 +518,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Decentralized Web", rskip60=False, ) + yield NetworkInfo( + chain_id=126, + slip44=126, + shortcut="OY", + name="OYchain", + rskip60=False, + ) yield NetworkInfo( chain_id=127, slip44=127, @@ -567,6 +602,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Permission", rskip60=False, ) + yield NetworkInfo( + chain_id=225, + slip44=60, + shortcut="LA", + name="LACHAIN", + rskip60=False, + ) yield NetworkInfo( chain_id=246, slip44=246, @@ -588,6 +630,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Huobi ECO Chain Testnet", rskip60=False, ) + yield NetworkInfo( + chain_id=258, + slip44=60, + shortcut="SETM", + name="Setheum", + rskip60=False, + ) yield NetworkInfo( chain_id=262, slip44=60, @@ -609,6 +658,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="KCC", rskip60=False, ) + yield NetworkInfo( + chain_id=333, + slip44=60, + shortcut="W3Q", + name="Web3Q", + rskip60=False, + ) yield NetworkInfo( chain_id=336, slip44=60, @@ -644,6 +700,20 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Rupaya", rskip60=False, ) + yield NetworkInfo( + chain_id=512, + slip44=1512, + shortcut="AAC", + name="Double-A Chain", + rskip60=False, + ) + yield NetworkInfo( + chain_id=555, + slip44=60, + shortcut="CLASS", + name="Vela1 Chain", + rskip60=False, + ) yield NetworkInfo( chain_id=558, slip44=60, @@ -665,6 +735,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Karura Network", rskip60=False, ) + yield NetworkInfo( + chain_id=707, + slip44=60, + shortcut="BCS", + name="BlockChain Station", + rskip60=False, + ) yield NetworkInfo( chain_id=777, slip44=60, @@ -770,6 +847,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Clover", rskip60=False, ) + yield NetworkInfo( + chain_id=1030, + slip44=60, + shortcut="CFX", + name="Conflux eSpace", + rskip60=False, + ) yield NetworkInfo( chain_id=1088, slip44=60, @@ -791,6 +875,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="MathChain Testnet", rskip60=False, ) + yield NetworkInfo( + chain_id=1197, + slip44=60, + shortcut="IORA", + name="Iora Chain", + rskip60=False, + ) yield NetworkInfo( chain_id=1202, slip44=60, @@ -805,6 +896,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Popcateum", rskip60=False, ) + yield NetworkInfo( + chain_id=1214, + slip44=60, + shortcut="ENTER", + name="EnterChain", + rskip60=False, + ) yield NetworkInfo( chain_id=1280, slip44=60, @@ -826,13 +924,6 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Moonriver", rskip60=False, ) - yield NetworkInfo( - chain_id=1286, - slip44=60, - shortcut="ROC", - name="Moonrock", - rskip60=False, - ) yield NetworkInfo( chain_id=1287, slip44=60, @@ -843,8 +934,8 @@ def _networks_iterator() -> Iterator[NetworkInfo]: yield NetworkInfo( chain_id=1288, slip44=60, - shortcut="MSHD", - name="Moonshadow", + shortcut="ROC", + name="Moonrock", rskip60=False, ) yield NetworkInfo( @@ -868,6 +959,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Teslafunds", rskip60=False, ) + yield NetworkInfo( + chain_id=1898, + slip44=60, + shortcut="BOY", + name="BON Network", + rskip60=False, + ) yield NetworkInfo( chain_id=1987, slip44=1987, @@ -903,6 +1001,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Ecoball", rskip60=False, ) + yield NetworkInfo( + chain_id=2213, + slip44=60, + shortcut="EVA", + name="Evanesco", + rskip60=False, + ) yield NetworkInfo( chain_id=2559, slip44=60, @@ -910,6 +1015,20 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Kortho", rskip60=False, ) + yield NetworkInfo( + chain_id=3400, + slip44=60, + shortcut="PRB", + name="Paribu Net", + rskip60=False, + ) + yield NetworkInfo( + chain_id=3966, + slip44=60, + shortcut="DYNO", + name="DYNO", + rskip60=False, + ) yield NetworkInfo( chain_id=4689, slip44=60, @@ -945,6 +1064,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Pixie Chain", rskip60=False, ) + yield NetworkInfo( + chain_id=8000, + slip44=60, + shortcut="TELE", + name="Teleport", + rskip60=False, + ) yield NetworkInfo( chain_id=8217, slip44=8217, @@ -966,6 +1092,20 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="bloxberg", rskip60=False, ) + yield NetworkInfo( + chain_id=9001, + slip44=60, + shortcut="EVMOS", + name="Evmos", + rskip60=False, + ) + yield NetworkInfo( + chain_id=9100, + slip44=60, + shortcut="GNC", + name="Genesis Coin", + rskip60=False, + ) yield NetworkInfo( chain_id=10101, slip44=60, @@ -973,6 +1113,20 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Blockchain Genesis", rskip60=False, ) + yield NetworkInfo( + chain_id=10823, + slip44=60, + shortcut="CCP", + name="CryptoCoinPay", + rskip60=False, + ) + yield NetworkInfo( + chain_id=11111, + slip44=60, + shortcut="WGM", + name="WAGMI", + rskip60=False, + ) yield NetworkInfo( chain_id=12052, slip44=621, @@ -980,6 +1134,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Singularity ZERO", rskip60=False, ) + yield NetworkInfo( + chain_id=13381, + slip44=60, + shortcut="PHX", + name="Phoenix", + rskip60=False, + ) yield NetworkInfo( chain_id=16000, slip44=60, @@ -994,6 +1155,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="BTCIX Network", rskip60=False, ) + yield NetworkInfo( + chain_id=21816, + slip44=60, + shortcut="OML", + name="omChain", + rskip60=False, + ) yield NetworkInfo( chain_id=24484, slip44=227, @@ -1059,9 +1227,9 @@ def _networks_iterator() -> Iterator[NetworkInfo]: ) yield NetworkInfo( chain_id=43114, - slip44=9000, + slip44=9005, shortcut="AVAX", - name="Avalanche", + name="Avalanche C-Chain", rskip60=False, ) yield NetworkInfo( @@ -1071,6 +1239,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Celo Alfajores Testnet", rskip60=False, ) + yield NetworkInfo( + chain_id=47805, + slip44=60, + shortcut="REI", + name="REI Network", + rskip60=False, + ) yield NetworkInfo( chain_id=49797, slip44=1, @@ -1078,6 +1253,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Energi Testnet", rskip60=False, ) + yield NetworkInfo( + chain_id=53935, + slip44=60, + shortcut="JEWEL", + name="DFK Chain", + rskip60=False, + ) yield NetworkInfo( chain_id=62320, slip44=1, @@ -1085,6 +1267,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Celo Baklava Testnet", rskip60=False, ) + yield NetworkInfo( + chain_id=63000, + slip44=60, + shortcut="ECS", + name="eCredits", + rskip60=False, + ) yield NetworkInfo( chain_id=73799, slip44=1, @@ -1103,7 +1292,14 @@ def _networks_iterator() -> Iterator[NetworkInfo]: chain_id=80001, slip44=1, shortcut="tMATIC", - name="Polygon Testnet Mumbai", + name="Mumbai", + rskip60=False, + ) + yield NetworkInfo( + chain_id=99999, + slip44=60, + shortcut="UBC", + name="UB Smart Chain", rskip60=False, ) yield NetworkInfo( @@ -1169,6 +1365,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="QuarkChain", rskip60=False, ) + yield NetworkInfo( + chain_id=108801, + slip44=60, + shortcut="BRO", + name="BROChain", + rskip60=False, + ) yield NetworkInfo( chain_id=200625, slip44=200625, @@ -1183,6 +1386,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Alaya", rskip60=False, ) + yield NetworkInfo( + chain_id=210425, + slip44=60, + shortcut="lat", + name="PlatON", + rskip60=False, + ) yield NetworkInfo( chain_id=246529, slip44=246529, @@ -1211,6 +1421,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Polis", rskip60=False, ) + yield NetworkInfo( + chain_id=888888, + slip44=60, + shortcut="VS", + name="Vision -", + rskip60=False, + ) yield NetworkInfo( chain_id=955305, slip44=1011, @@ -1239,6 +1456,13 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="Musicoin", rskip60=False, ) + yield NetworkInfo( + chain_id=11155111, + slip44=1, + shortcut="tSEP", + name="Sepolia", + rskip60=False, + ) yield NetworkInfo( chain_id=13371337, slip44=60, @@ -1309,13 +1533,6 @@ def _networks_iterator() -> Iterator[NetworkInfo]: name="IPOS Network", rskip60=False, ) - yield NetworkInfo( - chain_id=1313161554, - slip44=60, - shortcut="aETH", - name="Aurora", - rskip60=False, - ) yield NetworkInfo( chain_id=1666600000, slip44=60, diff --git a/core/src/apps/ethereum/tokens.py b/core/src/apps/ethereum/tokens.py index bfe6b3388..ab21c1dff 100644 --- a/core/src/apps/ethereum/tokens.py +++ b/core/src/apps/ethereum/tokens.py @@ -85,6 +85,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("AFA", 2) # eth / Africahead Ipparts if address == b"\x8e\xb2\x43\x19\x39\x37\x16\x66\x8d\x76\x8d\xce\xc2\x93\x56\xae\x9c\xff\xe2\x85": return TokenInfo("AGI", 8) # eth / SingularityNET + if address == b"\x73\x88\x65\x30\x1a\x9b\x7d\xd8\x0d\xc3\x66\x6d\xd4\x8c\xf0\x34\xec\x42\xbd\xda": + return TokenInfo("AGRS", 8) # eth / Agoras: Currency of Tau if address == b"\x7d\xb5\x45\x4f\x35\x00\xf2\x81\x71\xd1\xf9\xc7\xa3\x85\x27\xc9\xcf\x94\xe6\xb2": return TokenInfo("AGS", 4) # eth / Silver Standard if address == b"\x51\x21\xe3\x48\xe8\x97\xda\xef\x1e\xef\x23\x95\x9a\xb2\x90\xe5\x55\x7c\xf2\x74": @@ -113,6 +115,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("aLINK", 18) # eth / Aave Interest bearing LINK if address == b"\xea\x61\x0b\x11\x53\x47\x77\x20\x74\x8d\xc1\x3e\xd3\x78\x00\x39\x41\xd8\x4f\xab": return TokenInfo("ALIS", 18) # eth / ALIS Token + if address == b"\xe0\xcc\xa8\x6b\x25\x40\x05\x88\x9a\xc3\xa8\x1e\x73\x7f\x56\xa1\x4f\x4a\x38\xf5": + return TokenInfo("ALTA", 18) # eth / Alta Finance if address == b"\x63\x8a\xc1\x49\xea\x8e\xf9\xa1\x28\x6c\x41\xb9\x77\x01\x7a\xa7\x35\x9e\x6c\xfa": return TokenInfo("ALTS", 18) # eth / ALTS Token if address == b"\x49\xb1\x27\xbc\x33\xce\x7e\x15\x86\xec\x28\xce\xc6\xa6\x5b\x11\x25\x96\xc8\x22": @@ -521,8 +525,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("CHSB", 8) # eth / SwissBorg if address == b"\x14\x60\xa5\x80\x96\xd8\x0a\x50\xa2\xf1\xf9\x56\xdd\xa4\x97\x61\x1f\xa4\xf1\x65": return TokenInfo("CHX", 18) # eth / Own - if address == b"\x00\x38\x01\x43\x12\x91\x67\x39\x5e\x8b\x4f\x0a\x35\xed\xc1\xbc\x60\xe7\xce\x65": - return TokenInfo("CIG", 8) # eth / Clorigin if address == b"\x37\xfe\x0f\x06\x7f\xa8\x08\xff\xbd\xd1\x28\x91\xc0\x85\x85\x32\xcf\xe7\x36\x1d": return TokenInfo("CIV", 18) # eth / Civilization if address == b"\xf7\x5f\xbf\xa2\xf6\x81\x86\x0b\x9a\x6d\x19\xfc\x3f\xf3\xd3\x4c\xb3\x22\xe2\xd6": @@ -555,6 +557,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("CNB", 8) # eth / Canabio if address == b"\xd4\xc4\x35\xf5\xb0\x9f\x85\x5c\x33\x17\xc8\x52\x4c\xb1\xf5\x86\xe4\x27\x95\xfa": return TokenInfo("CND", 18) # eth / Cindicator + if address == b"\xbc\x13\x8b\xd2\x0c\x98\x18\x6c\xc0\x34\x2c\x8e\x38\x09\x53\xaf\x0c\xb4\x8b\xa8": + return TokenInfo("CNDL", 18) # eth / Candle if address == b"\x87\x13\xd2\x66\x37\xcf\x49\xe1\xb6\xb4\xa7\xce\x57\x10\x6a\xab\xc9\x32\x53\x43": return TokenInfo("CNN", 18) # eth / Content Neutrality Network if address == b"\xb4\xb1\xd2\xc2\x17\xec\x07\x76\x58\x4c\xe0\x8d\x3d\xd9\x8f\x90\xed\xed\xa4\x4b": @@ -677,8 +681,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("DACS", 18) # eth / DACSEE if address == b"\xfb\x2f\x26\xf2\x66\xfb\x28\x05\xa3\x87\x23\x0f\x2a\xa0\xa3\x31\xb4\xd9\x6f\xba": return TokenInfo("DADI", 18) # eth / DADI - if address == b"\x6b\x17\x54\x74\xe8\x90\x94\xc4\x4d\xa9\x8b\x95\x4e\xed\xea\xc4\x95\x27\x1d\x0f": - return TokenInfo("DAI", 18) # eth / Dai Stablecoin v2.0 + if address == b"\x1d\x01\x98\x82\x9c\xba\x76\x8e\x4e\xf2\xf7\x62\xcd\x82\x84\x2b\xba\x3e\x34\x58": + return TokenInfo("DAF", 6) # eth / Diamonds are Forever if address == b"\x07\xd9\xe4\x9e\xa4\x02\x19\x4b\xf4\x8a\x82\x76\xda\xfb\x16\xe4\xed\x63\x33\x17": return TokenInfo("DALC", 8) # eth / DaleCoin if address == b"\x9b\x70\x74\x0e\x70\x8a\x08\x3c\x6f\xf3\x8d\xf5\x22\x97\x02\x0f\x5d\xfa\xa5\xee": @@ -731,8 +735,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("DEX", 18) # eth / DEX if address == b"\x43\x1a\xd2\xff\x6a\x9c\x36\x58\x05\xeb\xad\x47\xee\x02\x11\x48\xd6\xf7\xdb\xe0": return TokenInfo("DF", 18) # eth / dForce Platform Token - if address == b"\xe0\xb7\x92\x7c\x4a\xf2\x37\x65\xcb\x51\x31\x4a\x0e\x05\x21\xa9\x64\x5f\x0e\x2a": - return TokenInfo("DGD", 9) # eth / Digix DAO if address == b"\xf6\xcf\xe5\x3d\x6f\xeb\xae\xea\x05\x1f\x40\x0f\xf5\xfc\x14\xf0\xcb\xbd\xac\xa1": return TokenInfo("DGPT", 18) # eth / DigiPulse if address == b"\x6a\xed\xbf\x8d\xff\x31\x43\x72\x20\xdf\x35\x19\x50\xba\x2a\x33\x62\x16\x8d\x1b": @@ -1213,8 +1215,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("GLA", 8) # eth / Gladius if address == b"\x68\x10\xe7\x76\x88\x0c\x02\x93\x3d\x47\xdb\x1b\x9f\xc0\x59\x08\xe5\x38\x6b\x96": return TokenInfo("GNO", 18) # eth / Gnosis - if address == b"\xa7\x44\x76\x44\x31\x19\xa9\x42\xde\x49\x85\x90\xfe\x1f\x24\x54\xd7\xd4\xac\x0d": - return TokenInfo("GNT", 18) # eth / Golem if address == b"\x6e\xc8\xa2\x4c\xab\xdc\x33\x9a\x06\xa1\x72\xf8\x22\x3e\xa5\x57\x05\x5a\xda\xa5": return TokenInfo("GNX", 9) # eth / Genaro Network if address == b"\x24\x75\x51\xf2\xeb\x33\x62\xe2\x22\xc7\x42\xe9\xc7\x88\xb8\x95\x7d\x9b\xc8\x7e": @@ -1255,8 +1255,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("GUESS", 2) # eth / Peerguess if address == b"\x98\x47\x34\x5d\xe8\xb6\x14\xc9\x56\x14\x6b\xbe\xa5\x49\x33\x6d\x9c\x8d\x26\xb6": return TokenInfo("GULD", 8) # eth / GULD ERC20 - if address == b"\xf7\xb0\x98\x29\x8f\x7c\x69\xfc\x14\x61\x0b\xf7\x1d\x5e\x02\xc6\x07\x92\x89\x4c": - return TokenInfo("GUP", 3) # eth / Matchpool if address == b"\x05\x6f\xd4\x09\xe1\xd7\xa1\x24\xbd\x70\x17\x45\x9d\xfe\xa2\xf3\x87\xb6\xd5\xcd": return TokenInfo("GUSD", 2) # eth / Gemini dollar if address == b"\x10\x3c\x3a\x20\x9d\xa5\x9d\x3e\x7c\x4a\x89\x30\x7e\x66\x52\x1e\x08\x1c\xfd\xf0": @@ -1503,8 +1501,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("KAN", 18) # eth / BitKan if address == b"\xe1\x52\x54\xa1\x3d\x34\xf9\x70\x03\x20\x33\x0a\xbc\xb7\xc7\xf8\x57\xaf\x2f\xb7": return TokenInfo("KAPA", 2) # eth / KAPA COIN - if address == b"\x0d\x6d\xd9\xf6\x8d\x24\xec\x1d\x5f\xe2\x17\x4f\x3e\xc8\xda\xb5\x2b\x52\xba\xf5": - return TokenInfo("KC", 18) # eth / KMCC if address == b"\x03\x9b\x56\x49\xa5\x99\x67\xe3\xe9\x36\xd7\x47\x1f\x9c\x37\x00\x10\x0e\xe1\xab": return TokenInfo("KCS", 6) # eth / KuCoin if address == b"\x72\xd3\x2a\xc1\xc5\xe6\x6b\xfc\x5b\x08\x80\x62\x71\xf8\xee\xf9\x15\x54\x51\x64": @@ -1625,6 +1621,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("[deprecated] LRC (old)", 18) # eth / Loopring if address == b"\x5d\xbe\x29\x6f\x97\xb2\x3c\x4a\x6a\xa6\x18\x3d\x73\xe5\x74\xd0\x2b\xa5\xc7\x19": return TokenInfo("LUC", 18) # eth / LUCToken + if address == b"\xa5\xef\x74\x06\x8d\x04\xba\x08\x09\xb7\x37\x9d\xd7\x6a\xf5\xce\x34\xab\x7c\x57": + return TokenInfo("LUCHOW", 18) # eth / LunaChow if address == b"\xfb\x12\xe3\xcc\xa9\x83\xb9\xf5\x9d\x90\x91\x2f\xd1\x7f\x8d\x74\x5a\x8b\x29\x53": return TokenInfo("LUCK", 0) # eth / LUCK if address == b"\x01\xcd\x3d\x9d\xf5\x86\x9c\xa7\x95\x47\x45\x66\x3b\xd6\x20\x1c\x57\x1e\x05\xcf": @@ -1667,6 +1665,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("MDT", 18) # eth / Measurable Data Token if address == b"\x94\x7a\xeb\x02\x30\x43\x91\xf8\xfb\xe5\xb2\x5d\x7d\x98\xd6\x49\xb5\x7b\x17\x88": return TokenInfo("MDX", 18) # eth / Mandala Exchange Token + if address == b"\x66\x52\xfa\x20\x1b\x6b\xbb\xc0\xb5\xb0\xad\x3f\x57\x02\xb2\xb9\x84\x9c\xc8\x30": + return TokenInfo("MEDCASH", 4) # eth / MEDCASH if address == b"\xfd\x1e\x80\x50\x8f\x24\x3e\x64\xce\x23\x4e\xa8\x8a\x5f\xd2\x82\x7c\x71\xd4\xb7": return TokenInfo("MEDX", 8) # eth / MediBloc [ERC20] if address == b"\xd5\x52\x5d\x39\x78\x98\xe5\x50\x20\x75\xea\x5e\x83\x0d\x89\x14\xf6\xf0\xaf\xfe": @@ -1701,14 +1701,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("MITH", 18) # eth / Mithril if address == b"\x4a\x52\x7d\x8f\xc1\x3c\x52\x03\xab\x24\xba\x09\x44\xf4\xcb\x14\x65\x8d\x1d\xb6": return TokenInfo("MITX", 18) # eth / Morpheus Infrastructure Token - if address == b"\x9f\x8f\x72\xaa\x93\x04\xc8\xb5\x93\xd5\x55\xf1\x2e\xf6\x58\x9c\xc3\xa5\x79\xa2": - return TokenInfo("MKR", 18) # eth / MakerDAO if address == b"\x79\x39\x88\x2b\x54\xfc\xf0\xbc\xae\x6b\x53\xde\xc3\x9a\xd6\xe8\x06\x17\x64\x42": return TokenInfo("MKT", 8) # eth / Mikado - if address == b"\xec\x67\x00\x5c\x4e\x49\x8e\xc7\xf5\x5e\x09\x2b\xd1\xd3\x5c\xbc\x47\xc9\x18\x92": - return TokenInfo("MLN (new)", 18) # eth / Melonport - if address == b"\xbe\xb9\xef\x51\x4a\x37\x9b\x99\x7e\x07\x98\xfd\xcc\x90\x1e\xe4\x74\xb6\xd9\xa1": - return TokenInfo("[deprecated] MLN (old)", 18) # eth / Melonport if address == b"\x6b\x4c\x7a\x5e\x3f\x0b\x99\xfc\xd8\x3e\x9c\x08\x9b\xdd\xd6\xc7\xfc\xe5\xc6\x11": return TokenInfo("MM", 18) # eth / Million if address == b"\x1a\x95\xb2\x71\xb0\x53\x5d\x15\xfa\x49\x93\x2d\xab\xa3\x1b\xa6\x12\xb5\x29\x46": @@ -1825,8 +1819,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("NOAH", 18) # eth / Noah Coin if address == b"\xf4\xfa\xea\x45\x55\x75\x35\x4d\x26\x99\xbc\x20\x9b\x0a\x65\xca\x99\xf6\x99\x82": return TokenInfo("NOBS", 18) # eth / No BS Crypto - if address == b"\x64\x3b\x68\x70\xbe\xab\xee\x94\x1b\x92\x60\xa0\xa8\x78\xbc\xf4\xa6\x1f\xb0\xf1": - return TokenInfo("NONE", 0) # eth / None if address == b"\x00\x27\x44\x9b\xf0\x88\x7c\xa3\xe4\x31\xd2\x63\xff\xde\xfb\x24\x4d\x95\xb5\x55": return TokenInfo("NOT", 18) # eth / Token Not if address == b"\xec\x46\xf8\x20\x7d\x76\x60\x12\x45\x4c\x40\x8d\xe2\x10\xbc\xbc\x22\x43\xe7\x1c": @@ -2153,8 +2145,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("RBX", 18) # eth / RBX if address == b"\xf9\x70\xb8\xe3\x6e\x23\xf7\xfc\x3f\xd7\x52\xee\xa8\x6f\x8b\xe8\xd8\x33\x75\xa6": return TokenInfo("RCN", 18) # eth / Ripio Credit Network - if address == b"\x25\x5a\xa6\xdf\x07\x54\x0c\xb5\xd3\xd2\x97\xf0\xd0\xd4\xd8\x4c\xb5\x2b\xc8\xe6": - return TokenInfo("RDN", 18) # eth / Raiden Network if address == b"\xd9\x67\xd9\xf9\x41\xcd\x31\x6a\xb2\x38\xd3\xee\x76\x1f\x80\xb7\xca\xec\x78\x19": return TokenInfo("RDV", 18) # eth / Rendezvous if address == b"\x76\x7b\xa2\x91\x5e\xc3\x44\x01\x5a\x79\x38\xe3\xee\xdf\xec\x27\x85\x19\x5d\x05": @@ -2177,10 +2167,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("REMI", 18) # eth / REMI if address == b"\x40\x8e\x41\x87\x6c\xcc\xdc\x0f\x92\x21\x06\x00\xef\x50\x37\x26\x56\x05\x2a\x38": return TokenInfo("REN", 18) # eth / Republic Token - if address == b"\x19\x85\x36\x5e\x9f\x78\x35\x9a\x9b\x6a\xd7\x60\xe3\x24\x12\xf4\xa4\x45\xe8\x62": - return TokenInfo("REP", 18) # eth / Augur - if address == b"\xe9\x43\x27\xd0\x7f\xc1\x79\x07\xb4\xdb\x78\x8e\x5a\xdf\x2e\xd4\x24\xad\xdf\xf6": - return TokenInfo("[deprecated] REP", 18) # eth / Augur if address == b"\x22\x16\x57\x77\x68\x46\x89\x09\x89\xa7\x59\xba\x29\x73\xe4\x27\xdf\xf5\xc9\xbb": return TokenInfo("REPv2", 18) # eth / Reputation if address == b"\x8f\x82\x21\xaf\xbb\x33\x99\x8d\x85\x84\xa2\xb0\x57\x49\xba\x73\xc3\x7a\x93\x8a": @@ -2205,8 +2191,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("RIYA", 8) # eth / Etheriya if address == b"\x10\x6a\xa4\x92\x95\xb5\x25\xfc\xf9\x59\xaa\x75\xec\x3f\x7d\xcb\xf5\x35\x2f\x1c": return TokenInfo("RKT", 18) # eth / Rock - if address == b"\x60\x7f\x4c\x5b\xb6\x72\x23\x0e\x86\x72\x08\x55\x32\xf7\xe9\x01\x54\x4a\x73\x75": - return TokenInfo("RLC", 9) # eth / IEx.ec if address == b"\xcc\xed\x5b\x82\x88\x08\x6b\xe8\xc3\x8e\x23\x56\x7e\x68\x4c\x37\x40\xbe\x4d\x48": return TokenInfo("RLT", 10) # eth / RouletteToken if address == b"\xbe\x99\xb0\x97\x09\xfc\x75\x3b\x09\xbc\xf5\x57\xa9\x92\xf6\x60\x5d\x59\x97\xb0": @@ -2241,6 +2225,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("RPE", 18) # eth / REPE if address == b"\xb4\xef\xd8\x5c\x19\x99\x9d\x84\x25\x13\x04\xbd\xa9\x9e\x90\xb9\x23\x00\xbd\x93": return TokenInfo("RPL", 18) # eth / Rocket Pool + if address == b"\x32\x06\x23\xb8\xe4\xff\x03\x37\x39\x31\x76\x9a\x31\xfc\x52\xa4\xe7\x8b\x5d\x70": + return TokenInfo("RSR", 18) # eth / Reserve Rights if address == b"\xec\x49\x1c\x10\x88\xea\xe9\x92\xb7\xa2\x14\xef\xb0\xa2\x66\xad\x09\x27\xa7\x2a": return TokenInfo("RTB", 18) # eth / AB-Chain RTB if address == b"\x7a\x55\x99\xb9\x7e\x8c\x4a\xbb\x5d\xd0\x6e\xba\x0e\x9d\x1f\x75\xaf\x81\x8d\xb9": @@ -2307,6 +2293,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("SETS", 18) # eth / Sensitrust Token if address == b"\x68\x47\x3d\xc4\xb7\xa4\xb0\x86\x7f\xd7\xc5\xb9\xa9\x82\xfe\xa4\x07\xda\xd3\x20": return TokenInfo("sEUR", 18) # eth / Synth sEUR + if address == b"\xaf\x50\xf8\xbe\xc1\xdb\xec\x01\x3b\x70\x25\xdb\x44\x4d\xa0\x19\xc2\xf5\xd4\x88": + return TokenInfo("SEV", 18) # eth / SeveraDAO if address == b"\x98\xf5\xe9\xb7\xf0\xe3\x39\x56\xc0\x44\x3e\x81\xbf\x7d\xeb\x8b\x5b\x1e\xd5\x45": return TokenInfo("SEXY", 18) # eth / Sexy Token if address == b"\xed\x08\x49\xbf\x46\xcf\xb9\x84\x5a\x2d\x90\x0a\x0a\x4e\x59\x3f\x2d\xd3\x67\x3c": @@ -2525,6 +2513,8 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("SXUT", 18) # eth / Spectre.ai U-Token if address == b"\x10\xb1\x23\xfd\xdd\xe0\x03\x24\x31\x99\xaa\xd0\x35\x22\x06\x5d\xc0\x58\x27\xa0": return TokenInfo("SYN", 18) # eth / Synapse + if address == b"\x46\xea\xf7\x5e\x6d\x39\x17\x08\xb7\xf1\xa0\xd5\x68\x75\xd9\x08\x44\x11\x95\x21": + return TokenInfo("SYS", 18) # eth / Syscoin if address == b"\x3a\x0d\x74\x6b\x3e\xa1\xd8\xcc\xdf\x19\xad\x91\x59\x13\xbd\x68\x39\x11\x33\xca": return TokenInfo("SYSX", 8) # eth / SyscoinToken if address == b"\xe7\x77\x5a\x6e\x9b\xcf\x90\x4e\xb3\x9d\xa2\xb6\x8c\x5e\xfb\x4f\x93\x60\xe0\x8c": @@ -3395,6 +3385,10 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("WINGS", 18) # eth / WINGS if address == b"\x1b\x22\xc3\x2c\xd9\x36\xcb\x97\xc2\x8c\x56\x90\xa0\x69\x5a\x82\xab\xf6\x88\xe6": return TokenInfo("WISH", 18) # eth / MyWish + if address == b"\xd6\x4d\xee\xa5\xf2\x49\x34\xe3\xa1\xaa\x75\x29\x12\xae\xe8\xff\xd8\x30\x0c\x3f": + return TokenInfo("WLKR", 18) # eth / WLKR Innovation Index + if address == b"\xc9\x02\x06\xab\x21\xbd\xbf\x5e\x92\xaf\xf4\xe6\xb5\xf0\x97\xb6\x5b\x0e\xcc\x06": + return TokenInfo("WLKRR", 18) # eth / Walker if address == b"\x68\x5e\xd3\x90\xb1\x6a\xc9\xdf\x9a\xb9\x70\x72\x94\xa4\x2a\x10\x7c\xfb\x62\xaf": return TokenInfo("WMA", 18) # eth / weeMarketplaceAccessToken if address == b"\xbf\xbe\x53\x32\xf1\x72\xd7\x78\x11\xbc\x6c\x27\x28\x44\xf3\xe5\x4a\x7b\x23\xbb": @@ -3561,8 +3555,6 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("ZMN", 18) # eth / ZMINE if address == b"\xb5\xb8\xf5\x61\x6f\xe4\x2d\x5c\xec\xa3\xe8\x7f\x3f\xdd\xbd\xd8\xf4\x96\xd7\x60": return TokenInfo("ZPR", 18) # eth / ZPER - if address == b"\xe4\x1d\x24\x89\x57\x1d\x32\x21\x89\x24\x6d\xaf\xa5\xeb\xde\x1f\x46\x99\xf4\x98": - return TokenInfo("ZRX", 18) # eth / 0x Project if address == b"\xe3\x86\xb1\x39\xed\x37\x15\xca\x4b\x18\xfd\x52\x67\x1b\xdc\xea\x1c\xdf\xe4\xb1": return TokenInfo("ZST", 8) # eth / Zeus Exchange if address == b"\xe8\xf9\xfa\x97\x7e\xa5\x85\x59\x1d\x9f\x39\x46\x81\x31\x8c\x16\x55\x25\x77\xfb": @@ -3578,27 +3570,17 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("ILSC", 2) # rop / IsraCoin if address == b"\x4c\x57\x2f\xbc\x03\xd4\xa2\xb6\x83\xcf\x4f\x10\xff\xdc\xaf\xd0\x08\x85\xe1\x08": return TokenInfo("MEWV5", 9) # rop / MEW V5 Test Token - if address == b"\xfd\x5a\x69\xa1\x30\x95\x95\xff\x51\x21\x55\x3f\x52\xc8\xa5\xb2\xb1\xb3\x10\x31": - return TokenInfo("NONE", 0) # rop / None - if address == b"\x73\x14\xdc\x4d\x77\x94\xb5\xe7\x89\x42\x12\xca\x15\x56\xae\x8e\x3d\xe5\x86\x21": - return TokenInfo("RLC", 9) # rop / iExec RLC + if address == b"\xaa\x1d\x9d\x07\x88\xda\xca\x9a\x30\x11\x1d\x12\xaa\x0d\x98\x09\x0f\x02\xea\x30": + return TokenInfo("RCL", 18) # rop / RascalCoin if chain_id == 4: if address == b"\xe2\x78\x26\xee\x77\x8b\x6f\x78\xa4\x9a\x68\x6d\xa7\xd6\x4f\x6e\x7b\x08\x4a\x4f": return TokenInfo("BHNT", 0) # rin / Berlin Hack&Tell winner token if address == b"\x8b\x65\xd4\xb7\xee\x3f\xff\xa9\x86\xc5\x77\xf0\xf4\xb7\x0a\x21\xba\xe3\xdd\x54": return TokenInfo("CTGA", 18) # rin / Convenient To Go - if address == b"\x27\x5a\x5b\x34\x65\x99\xb5\x69\x17\xe7\xb1\xc9\xde\x01\x9d\xcf\x9e\xad\x86\x1a": - return TokenInfo("KC", 18) # rin / Karma Token - if address == b"\x64\x75\xa7\xfa\x6e\xd2\xd5\x18\x0f\x0e\x0a\x07\xc2\xd9\x51\xd1\x2c\x0e\xdb\x91": - return TokenInfo("NONE", 0) # rin / None if address == b"\x12\xfe\x17\x4c\x09\x7f\x6b\x3e\x87\x6b\x3b\x06\x0c\x90\x61\xf4\xb9\xde\xbb\x80": return TokenInfo("PPD", 18) # rin / PP Donation if address == b"\x2d\x42\x7d\x9e\x53\x5e\x43\x82\x60\x6b\x93\x29\x0d\xcc\x13\xa5\xe9\xa6\x94\xbe": return TokenInfo("qwe", 18) # rin / qweToken - if address == b"\x36\x15\x75\x70\x11\x11\x25\x60\x52\x15\x36\x25\x8c\x1e\x73\x25\xae\x3b\x48\xae": - return TokenInfo("RDN", 18) # rin / Raiden - if address == b"\xf1\xe6\xad\x3a\x7e\xf0\xc8\x6c\x91\x5f\x0f\xed\xf8\x0e\xd8\x51\x80\x9b\xea\x90": - return TokenInfo("RLC", 9) # rin / iExec RLC if address == b"\x0a\x05\x7a\x87\xce\x9c\x56\xd7\xe3\x36\xb4\x17\xc7\x9c\xf3\x0e\x8d\x27\x86\x0b": return TokenInfo("WALL", 15) # rin / WALLETH Community-Token if chain_id == 8: @@ -3608,10 +3590,26 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: return TokenInfo("CEFS", 8) # ubq / CEFS if address == b"\x94\xad\x7e\x41\xc1\xd4\x40\x22\xc4\xf4\x7c\xb1\xba\x01\x9f\xd1\xa0\x22\xc5\x36": return TokenInfo("DOT", 8) # ubq / DOT + if address == b"\xcf\x32\x22\xb7\xfd\xa7\xa7\x56\x3b\x9e\x1e\x6c\x96\x6b\xea\xd0\x4a\xc2\x3c\x36": + return TokenInfo("ESCH", 18) # ubq / Escher + if address == b"\x50\x06\x84\xce\x0d\x4f\x04\xab\xed\xff\x3e\x54\xfc\xf8\xac\xc5\xe6\xcf\xc4\xbd": + return TokenInfo("GEO", 8) # ubq / GeoCoin + if address == b"\x08\x26\x18\x0a\x4c\x98\x1d\x50\x95\xcb\x5c\x48\xbb\x2a\x09\x8a\x44\xcf\x6f\x73": + return TokenInfo("GRANS", 18) # ubq / 10grans + if address == b"\x78\x45\xfc\xbe\x28\xac\x19\xab\x7e\xc1\xc1\xd9\x67\x4e\x34\xfd\xcb\x49\x17\xdb": + return TokenInfo("INK", 18) # ubq / INK if address == b"\x4b\x48\x99\xa1\x0f\x3e\x50\x7d\xb2\x07\xb0\xee\x24\x26\x02\x9e\xfa\x16\x8a\x67": return TokenInfo("QWARK", 8) # ubq / QWARK if address == b"\x5e\x17\x15\xbb\x79\x80\x5b\xd6\x72\x72\x97\x60\xb3\xf7\xf3\x4d\x6f\x48\x50\x98": return TokenInfo("RICKS", 8) # ubq / RICKS + if address == b"\x49\x7e\x20\x58\x6f\x86\xc3\x55\x92\xff\x8f\x65\xcd\xe9\x4f\x29\x65\x14\xc3\x87": + return TokenInfo("SNARG", 0) # ubq / Snarg01 + if address == b"\x20\xe3\xdd\x74\x6d\xdf\x51\x9b\x23\xff\xbb\xb6\xda\x7a\x5d\x33\xea\x63\x49\xd6": + return TokenInfo("SPHR", 8) # ubq / Sphere + if address == b"\x40\x2c\x2c\x3a\xce\xeb\x52\xb8\x65\x4a\x06\x31\x01\x2c\xed\x49\xcb\xc9\xbd\xc4": + return TokenInfo("SPHRC", 18) # ubq / Sphere Cubed + if address == b"\xcf\x82\x3e\xb6\xf6\x2a\x30\xed\xb0\x05\xb9\x13\x83\xe2\xfa\x36\x4d\xd7\x53\xdc": + return TokenInfo("TGE1", 18) # ubq / Ubiq TGE 1 if chain_id == 30: if address == b"\xd5\x2d\xa6\x36\x89\x54\x39\x24\xdc\xa6\x6b\xcb\xe2\xe2\xea\x59\x9c\x45\xd5\x75": return TokenInfo("ARSCB", 18) # rsk / Pesos Argentinos PagoLinea @@ -3692,30 +3690,10 @@ def token_by_chain_address(chain_id: int, address: bytes) -> TokenInfo: if chain_id == 42: if address == b"\x86\x67\x55\x92\x54\x24\x1d\xde\xd4\xd1\x13\x92\xf8\x68\xd7\x20\x92\x76\x53\x67": return TokenInfo("Aeternity", 18) # kov / Aeternity - if address == b"\xc4\x37\x5b\x7d\xe8\xaf\x5a\x38\xa9\x35\x48\xeb\x84\x53\xa4\x98\x22\x2c\x4f\xf2": - return TokenInfo("DAI", 18) # kov / RadarRelay test Dai Stablecoin v1.0 - if address == b"\xee\xe3\x87\x06\x57\xe4\x71\x66\x70\xf1\x85\xdf\x08\x65\x2d\xd8\x48\xfe\x8f\x7e": - return TokenInfo("DGD", 18) # kov / RadarRelay test Digix DAO Token if address == b"\x47\x33\x65\x9a\x5c\xb7\x89\x6a\x65\xc9\x18\xad\xd6\xf5\x9c\x51\x48\xfb\x5f\xfa": return TokenInfo("GAV", 6) # kov / GavCoin - if address == b"\xef\x7f\xff\x64\x38\x9b\x81\x4a\x94\x6f\x3e\x92\x10\x55\x13\x70\x5c\xa6\xb9\x90": - return TokenInfo("GNT", 18) # kov / RadarRelay test Golem Network Token - if address == b"\x3c\x67\xf7\xd4\xde\xcf\x77\x95\x22\x5f\x51\xb5\x41\x34\xf8\x11\x37\x38\x5f\x83": - return TokenInfo("GUP", 3) # kov / GUP - if address == b"\x1d\xad\x47\x83\xcf\x3f\xe3\x08\x5c\x14\x26\x15\x7a\xb1\x75\xa6\x11\x9a\x04\xba": - return TokenInfo("MKR", 18) # kov / RadarRelay test MakerDAO - if address == b"\xaa\xf6\x4b\xfc\xc3\x2d\x0f\x15\x87\x3a\x02\x16\x3e\x7e\x50\x06\x71\xa4\xff\xcd": - return TokenInfo("MKR", 18) # kov / MakerDAO - if address == b"\x32\x3b\x5d\x4c\x32\x34\x5c\xed\x77\x39\x3b\x35\x30\xb1\xee\xd0\xf3\x46\x42\x9d": - return TokenInfo("MLN", 18) # kov / RadarRelay test Melon Tokens - if address == b"\xb1\x88\x45\xc2\x60\xf6\x80\xd5\xb9\xd8\x46\x49\x63\x88\x13\xe3\x42\xe4\xf8\xc9": - return TokenInfo("REP", 18) # kov / RadarRelay test Augur Reputation Token - if address == b"\xc5\x75\x38\x84\x6e\xc4\x05\xea\x25\xde\xb0\x0e\x0f\x9b\x29\xa4\x32\xd5\x35\x07": - return TokenInfo("RLC", 9) # kov / iExec RLC if address == b"\x4a\x6e\x6c\x38\x68\xa2\x79\xe1\xd9\x04\x7b\x42\xc3\xfb\x35\x6f\xf4\x68\x00\x03": return TokenInfo("TIB", 18) # kov / ThibCoin - if address == b"\x6f\xf6\xc0\xff\x1d\x68\xb9\x64\x90\x1f\x98\x6d\x4c\x9f\xa3\xac\x68\x34\x65\x70": - return TokenInfo("ZRX", 18) # kov / RadarRelay test 0x Protocol Token if chain_id == 61: if address == b"\x08\x5f\xb4\xf2\x40\x31\xea\xed\xbc\x2b\x61\x1a\xa5\x28\xf2\x23\x43\xeb\x52\xdb": return TokenInfo("BEC", 8) # etc / BEC From 7d93bd317954144b44e23db2708c22fdbd52dafb Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 19 Apr 2022 16:33:17 +0200 Subject: [PATCH 26/32] fix(legacy/bootloader): erase storage if going below fix_version --- .../bootloader/.changelog.d/noissue.security | 1 + legacy/bootloader/usb.c | 52 ++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 legacy/bootloader/.changelog.d/noissue.security diff --git a/legacy/bootloader/.changelog.d/noissue.security b/legacy/bootloader/.changelog.d/noissue.security new file mode 100644 index 000000000..a18706c01 --- /dev/null +++ b/legacy/bootloader/.changelog.d/noissue.security @@ -0,0 +1 @@ +Erase storage when downgrading below fix_version. diff --git a/legacy/bootloader/usb.c b/legacy/bootloader/usb.c index 3698622ea..3253ac508 100644 --- a/legacy/bootloader/usb.c +++ b/legacy/bootloader/usb.c @@ -156,6 +156,51 @@ static secbool readprotobufint(const uint8_t **ptr, uint32_t *result) { return sectrue; } +/** Reverse-endian version comparison + * + * Versions are loaded from the header via a packed struct image_header. A + * version is represented as a single uint32_t. Arm is natively little-endian, + * but the version is actually stored as four bytes in major-minor-patch-build + * order. This function implements `cmp` with "lowest" byte first. + */ +static int version_compare(const uint32_t vera, const uint32_t verb) { + int a, b; // signed temp values so that we can safely return a signed result + a = vera & 0xFF; + b = verb & 0xFF; + if (a != b) return a - b; + a = (vera >> 8) & 0xFF; + b = (verb >> 8) & 0xFF; + if (a != b) return a - b; + a = (vera >> 16) & 0xFF; + b = (verb >> 16) & 0xFF; + if (a != b) return a - b; + a = (vera >> 24) & 0xFF; + b = (verb >> 24) & 0xFF; + return a - b; +} + +static int should_keep_storage(int old_was_signed, + uint32_t fix_version_current) { + // if the current firmware is unsigned, always erase storage + if (SIG_OK != old_was_signed) return SIG_FAIL; + + const image_header *new_hdr = (const image_header *)FW_HEADER; + // if the new header is unsigned, erase storage + if (SIG_OK != signatures_new_ok(new_hdr, NULL)) return SIG_FAIL; + // if the new header hashes don't match flash contents, erase storage + if (SIG_OK != check_firmware_hashes(new_hdr)) return SIG_FAIL; + + // going from old-style header to new-style is always an upgrade, keep storage + if (firmware_present_old()) return SIG_OK; + + // if the current fix_version is higher than the new one, erase storage + if (version_compare(new_hdr->version, fix_version_current) < 0) { + return SIG_FAIL; + } + + return SIG_OK; +} + static void rx_callback(usbd_device *dev, uint8_t ep) { (void)ep; static uint16_t msg_id = 0xFFFF; @@ -163,6 +208,7 @@ static void rx_callback(usbd_device *dev, uint8_t ep) { static uint32_t w; static int wi; static int old_was_signed; + static uint32_t fix_version_current = 0xffffffff; if (usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_OUT, buf, 64) != 64) return; @@ -235,10 +281,13 @@ static void rx_callback(usbd_device *dev, uint8_t ep) { (const image_header *)FLASH_PTR(FLASH_FWHEADER_START); old_was_signed = signatures_new_ok(hdr, NULL) & check_firmware_hashes(hdr); + fix_version_current = hdr->fix_version; } else if (firmware_present_old()) { old_was_signed = signatures_old_ok(); + fix_version_current = 0; } else { old_was_signed = SIG_FAIL; + fix_version_current = 0xffffffff; } erase_code_progress(); send_msg_success(dev); @@ -388,8 +437,7 @@ static void rx_callback(usbd_device *dev, uint8_t ep) { // 1) old firmware was unsigned or not present // 2) signatures are not OK // 3) hashes are not OK - if (SIG_OK != old_was_signed || SIG_OK != signatures_new_ok(hdr, NULL) || - SIG_OK != check_firmware_hashes(hdr)) { + if (SIG_OK != should_keep_storage(old_was_signed, fix_version_current)) { // erase storage erase_storage(); // check erasure From ed8cdef331d117904f87a9a7d77736fb58354567 Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 22 Apr 2022 14:18:30 +0200 Subject: [PATCH 27/32] chore(legacy/bootloader): bump major version --- legacy/bootloader/version.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/legacy/bootloader/version.h b/legacy/bootloader/version.h index 29d9a2ae1..c0c3d1f88 100644 --- a/legacy/bootloader/version.h +++ b/legacy/bootloader/version.h @@ -1,7 +1,7 @@ #define VERSION_MAJOR 1 -#define VERSION_MINOR 10 -#define VERSION_PATCH 1 +#define VERSION_MINOR 11 +#define VERSION_PATCH 0 #define VERSION_MAJOR_CHAR "\x01" -#define VERSION_MINOR_CHAR "\x0A" -#define VERSION_PATCH_CHAR "\x01" +#define VERSION_MINOR_CHAR "\x0B" +#define VERSION_PATCH_CHAR "\x00" From bc1ebdccdc7dff9fd4571a66ca915ced449b498e Mon Sep 17 00:00:00 2001 From: matejcik Date: Mon, 25 Apr 2022 11:42:35 +0200 Subject: [PATCH 28/32] build(legacy): add explicit dependency on version.h for the header object --- legacy/firmware/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/legacy/firmware/Makefile b/legacy/firmware/Makefile index d51f82921..3fda50670 100644 --- a/legacy/firmware/Makefile +++ b/legacy/firmware/Makefile @@ -183,6 +183,8 @@ bl_data.h: bl_data.py bootloader.dat @printf " PYTHON bl_data.py\n" $(Q)$(PYTHON) bl_data.py +header.o: version.h + clean:: rm -f bl_data.h find -maxdepth 1 -name "*.mako" | sed 's/.mako$$//' | xargs rm -f From 768d577d7823716a7becc93aca2cace387985c49 Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 22 Apr 2022 14:37:44 +0200 Subject: [PATCH 29/32] feat(legacy/bootloader): report installed firmware version --- legacy/bootloader/.changelog.d/2231.added | 1 + legacy/bootloader/usb_send.h | 80 ++++++++++++++++------- 2 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 legacy/bootloader/.changelog.d/2231.added diff --git a/legacy/bootloader/.changelog.d/2231.added b/legacy/bootloader/.changelog.d/2231.added new file mode 100644 index 000000000..2579a6a77 --- /dev/null +++ b/legacy/bootloader/.changelog.d/2231.added @@ -0,0 +1 @@ +Bootloader will report version of installed firmware. diff --git a/legacy/bootloader/usb_send.h b/legacy/bootloader/usb_send.h index 954008211..cfcb8cbaf 100644 --- a/legacy/bootloader/usb_send.h +++ b/legacy/bootloader/usb_send.h @@ -37,7 +37,7 @@ static void send_msg_failure(usbd_device *dev, uint8_t code) { static void send_msg_features(usbd_device *dev) { uint8_t response[64]; memzero(response, sizeof(response)); - // response: Features message (id 17), payload len 26 + // response: Features message (id 17), payload len 26 / 41 // - vendor = "trezor.io" // - major_version = VERSION_MAJOR // - minor_version = VERSION_MINOR @@ -45,28 +45,62 @@ static void send_msg_features(usbd_device *dev) { // - bootloader_mode = True // - firmware_present = True/False // - model = "1" - memcpy(response, - // header - "?##" - // msg_id - "\x00\x11" - // msg_size - "\x00\x00\x00\x1a" - // data - "\x0a" - "\x09" - "trezor.io" - "\x10" VERSION_MAJOR_CHAR "\x18" VERSION_MINOR_CHAR - "\x20" VERSION_PATCH_CHAR - "\x28" - "\x01" - "\x90\x01" - "\x00" - "\xaa" - "\x01\x01" - "1", - 35); - response[30] = firmware_present_new() ? 0x01 : 0x00; + // ? fw_version_major = version_major + // ? fw_version_minor = version_minor + // ? fw_version_patch = version_patch + const bool firmware_present = firmware_present_new(); + const image_header *current_hdr = (const image_header *)FLASH_FWHEADER_START; + uint32_t version = firmware_present ? current_hdr->version : 0; + + // clang-format off + const uint8_t feature_bytes[] = { + 0x0a, // vendor field + 0x09, // vendor length + 't', 'r', 'e', 'z', 'o', 'r', '.', 'i', 'o', + 0x10, VERSION_MAJOR, + 0x18, VERSION_MINOR, + 0x20, VERSION_PATCH, + 0x28, 0x01, // bootloader_mode + 0x90, 0x01, // firmware_present field + firmware_present ? 0x01 : 0x00, + 0xaa, 0x01, // model field + 0x01, // model length + '1', + }; + + const uint8_t version_bytes[] = { + // fw_version_major + 0xb0, 0x01, version & 0xff, + // fw_version_minor + 0xb8, 0x01, (version >> 8) & 0xff, + // fw_version_patch + 0xc0, 0x01, (version >> 16) & 0xff, + }; + + uint8_t header_bytes[] = { + // header + '?', '#', '#', + // msg_id + 0x00, 0x11, + // msg_size + 0x00, 0x00, 0x00, sizeof(feature_bytes) + (firmware_present ? sizeof(version_bytes) : 0), + }; + // clang-format on + + // Check that the response will fit into an USB packet, and also that the + // sizeof expression above fits into a single byte + _Static_assert( + sizeof(feature_bytes) + sizeof(version_bytes) + sizeof(header_bytes) <= + 64, + "Features response too long"); + + memcpy(response, header_bytes, sizeof(header_bytes)); + memcpy(response + sizeof(header_bytes), feature_bytes, sizeof(feature_bytes)); + if (firmware_present) { + memcpy(response + sizeof(header_bytes) + sizeof(feature_bytes), + version_bytes, sizeof(version_bytes)); + } + while (usbd_ep_write_packet(dev, ENDPOINT_ADDRESS_IN, response, 64) != 64) { } } From a1984f32758763cd7a93c41e04a5a27a9f39fc2d Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 29 Apr 2022 15:43:08 +0200 Subject: [PATCH 30/32] chore(legacy): release bootloader 1.11.0 --- legacy/bootloader/.changelog.d/1642.security | 1 - legacy/bootloader/.changelog.d/1884.fixed | 1 - legacy/bootloader/.changelog.d/2231.added | 1 - .../bootloader/.changelog.d/noissue.security | 1 - legacy/bootloader/CHANGELOG.md | 16 ++++++++++++++++ legacy/firmware/bl_check.c | 6 ++++++ legacy/firmware/bootloader.dat | Bin 32768 -> 32768 bytes 7 files changed, 22 insertions(+), 4 deletions(-) delete mode 100644 legacy/bootloader/.changelog.d/1642.security delete mode 100644 legacy/bootloader/.changelog.d/1884.fixed delete mode 100644 legacy/bootloader/.changelog.d/2231.added delete mode 100644 legacy/bootloader/.changelog.d/noissue.security diff --git a/legacy/bootloader/.changelog.d/1642.security b/legacy/bootloader/.changelog.d/1642.security deleted file mode 100644 index cc5ff3093..000000000 --- a/legacy/bootloader/.changelog.d/1642.security +++ /dev/null @@ -1 +0,0 @@ -Avoid accidental build with broken stack protector diff --git a/legacy/bootloader/.changelog.d/1884.fixed b/legacy/bootloader/.changelog.d/1884.fixed deleted file mode 100644 index 35202af07..000000000 --- a/legacy/bootloader/.changelog.d/1884.fixed +++ /dev/null @@ -1 +0,0 @@ -Compress firmware verification coordinates to be able link bootloader into preallocated space. diff --git a/legacy/bootloader/.changelog.d/2231.added b/legacy/bootloader/.changelog.d/2231.added deleted file mode 100644 index 2579a6a77..000000000 --- a/legacy/bootloader/.changelog.d/2231.added +++ /dev/null @@ -1 +0,0 @@ -Bootloader will report version of installed firmware. diff --git a/legacy/bootloader/.changelog.d/noissue.security b/legacy/bootloader/.changelog.d/noissue.security deleted file mode 100644 index a18706c01..000000000 --- a/legacy/bootloader/.changelog.d/noissue.security +++ /dev/null @@ -1 +0,0 @@ -Erase storage when downgrading below fix_version. diff --git a/legacy/bootloader/CHANGELOG.md b/legacy/bootloader/CHANGELOG.md index 8c3a9d756..ca0507070 100644 --- a/legacy/bootloader/CHANGELOG.md +++ b/legacy/bootloader/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 1.11.0 [May 2022] + +### Added +- Bootloader will report version of installed firmware. [#2231] + +### Fixed +- Compress firmware verification coordinates to be able link bootloader into preallocated space. [#1884] + +### Security +- Erase storage when downgrading below fix_version. +- Avoid accidental build with broken stack protector [#1642] + + ## 1.10.0 [May 2021] ### Added @@ -112,3 +125,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Initial import of code. [#1461]: https://github.com/trezor/trezor-firmware/pull/1461 +[#1642]: https://github.com/trezor/trezor-firmware/pull/1642 +[#1884]: https://github.com/trezor/trezor-firmware/pull/1884 +[#2231]: https://github.com/trezor/trezor-firmware/pull/2231 diff --git a/legacy/firmware/bl_check.c b/legacy/firmware/bl_check.c index d38cb8fa5..eeb5eb225 100644 --- a/legacy/firmware/bl_check.c +++ b/legacy/firmware/bl_check.c @@ -132,6 +132,12 @@ static int known_bootloader(int r, const uint8_t *hash) { "\xb9\xc7\xf6\x03\xcd\xc7\x30\xe7\x30\x78\x50\xa3\xf4\xd6\x2a\x5c", 32)) return 1; // 1.10.0 shipped with fw 1.10.0 + if (0 == + memcmp(hash, + "\xfa\x12\xa4\x4f\xa0\x5f\xd1\xd2\x05\x39\x35\x8b\x54\xf3\x01\xce" + "\xe4\xc3\x21\x9c\x9f\x1b\xb3\xa5\x77\x2f\xfd\x60\x9a\xf9\xe8\xe2", + 32)) + return 1; // 1.11.0 shipped with fw 1.11.1 return 0; } #endif diff --git a/legacy/firmware/bootloader.dat b/legacy/firmware/bootloader.dat index 604efd79583f22ad7e18903cfe9a2e098bdfc905..ac9d56f2307c80722bd3ca49998efa776cac2de7 100644 GIT binary patch delta 15558 zcmc(G3wTt;`S+a5W;dIJY_hp0Bzp-Ea$_MN0Th-^I3`&jh?gQ#4HxZFP$QrQirq!D z#tRiVRFTBi3$1{PNiaxiB~<)dtgU7h+9)7+sS%=h!fj9XcD~=7>?VQs`JSiG|9hT~ zhu_XSb7tOoXXc%E-nqo%VLcw!Eh~)atuaK`ZzZ}Z`9ya!FlX@q$W{Ml77$%6zR_eF zK0kISZ?w#R8M+56`!5UrKPu<`U$@|YC&;8oS4-{BwPZVEUgw2M3o#c6*{*c4Rw7)f z5F?cZ_&$?%f?yJKX5BsDFxJtz!0Q zq|APCp=RP#Uh;(+I?`%xk_!weRm`ir^kb;J!-)78gF%h=gsNJJNsBhdM%u`sje12q zqRG+!>E}deM-@lbisv-NRUX-HetZ`%EeqSt&mpWsxEtXjbeu(~z35rY?Aj!MGhvhb zFW}n=8tHd3RkV{bKQTHN80np`xFlve&q&Q-ac4|9`x{yOB4*JdUNVOcbZnEqOg2_A zQ*M^c28eqpV-+u@h87_GtK@`X=>UpP%vW9P(YMsUL%Wo=0Mb9BEkK0{ zVewt<#8RDHdvX0t6Z(ml-cwAL@dC3;Bi*Rbj>sCutq2`)A|&SP3JtvUJTfx7V|r&9 zG*Xcw-ma^3FY@c1oP~&t*={un8tEoKo%Y<|tYV}mLp&WMb=q%=CpugET&LK=3wATJ zE8CT%&L>_XA;otvObUq9=(*mRwcKjmB*)wI)*0rcQJdrhTP)(dVUw(zXEm=v$_U#U zq-fkoiUAUB#C#_b4D&Y0Df3E^L5tK_Ko7(LNw!UL>b!N<<@h$zP+;C9CnF_o-o4fg zq~sblBgKf6bRcV-nG*kgpLqvJ`ZmZ3e_xwXaaHuD&`p>DiAm{7yKYH;1)N?yku z&Z-|`y<25X2Pev!0qcXoWDE{vs=b>IO@bh{q&V$YaV-lP!1WVZPd<@H80J3#&K?ZG zJiGPwsO0PZBm1X=ROW%Prxj@1<6xTxj65%S!o0LOOj{c@>QtorgB-QOy}Y#NpjfQW zDCVVPg*9^~UK*j$d3JSy8wU$Kb5N|;J8~Uimt~6Jf;L_kb_u+6F5nUhvtxUChL_lo z*riW#^U~$uTbDdDE`RD0vUl^6J5*dd-et0AduJwPV(5MEjwW+wilXQGRlm{|Npx5=#Stu!dUmqMiAlJ{Uw ze#<-GNsrMX%GWR^8*m!tvI}#XFpOy;;?rRsk0D+Ry5x*h`=+zK7AtmSm7XfttqcZK zBf)ePn7wbzDQZa26pid+i`dWjBD*wK{4s9i4LfW0x21W=`7b;VbeIIicOk@Bi|U&p ze{>Cx^JY>}o}OGf!u!mybUJ8t0h6G9tyO&gc!w#C_ihq@8lUc7eo#}oz)QwF?tG%= z?`PQ62&)*{yjbQ)%8`Spcnb;#H55gx9;Hu!y2>E%b0)Y!Ph_)1lkywUUx($ zMDfiJN2}KAZi`gCZm{Y%2CIHRt(ur`gxEV#`@tZOHJ^6qKSQk5-cu_nWt8JzzvMCJ z72jny#4DdLBUe+D{OjM7^hw55BzzgVX)O6iJKi+-k-9D7B{QEyDH zo;+CcUlvsLh#GHx850z3-Ce-k)_3uxwFTrd+`? zxOa5*$kW>KIb)A|Ga4+_21!b+?jjaun!e81&x|95f#UIs%1tO0HZsE=?b!dBoz;9DT7?B~FYDtr=r zg&@*32-#k;N?#Y>$7;9s?7LJyZeKTVDHrxvYa~}7M)0%_h&f#qvo+Gl3hJJ^FFvt% zZ}l5hOMB=7z84dCWj~$DuYvkmKZgN&)mbj&){Pe?3uVIYIlE_{l6SpZ=sG3u{OXk4 zD4G*9HM94c>#D^WiDTU7PCx4;=BKN2U5YO~V4r1|B+rvoitl-qKI>6@DgLUC&t!w) zeA|a@qGLkWjx17m==@21(S%OP`45wEzy^30%q}2R9n8ZYLh(PPPQ`7W(mx-M0!5(O(gr!HkP@_A0(v{!{XT4Kc#>TAGr)_mnKV zHxqLe70MqY(D1DPGdaZ;W5=ATn^vd$mMQwMiz_11E1seTzQ}#?XRpKGM&H+fm0`mv zdD~|DtQi;c-*7my8?*8KC-|OYf!n=BBc1STcT=99^lNv8eWDWf9aFS$>DJvh8MC=5 zP)4Uq1&V9mP<#$J*U^H9{IwU!%yCs(I8*EWCQE6x7HdeHpGuwZhDnGuE56f#vDJlD zVc#dp$bXT}H=*%#O5{Lm^MTW3z^qdfUx_^oHS>0aG`>CJ9n)q1Q8zL-0egX{8%?Lh zpAo+ar~^EQKVTXV(w)nF_(t9CM-kHL)r9c(0NsF3pQqi#pO}C>Nb#9Qx+9@!`EOwW#pze4-* zr66^Ms=pzf1rU?YblN9WOln4G-&BslPqgD`JE(_&^{=Ab`50C|jp|t{KI|Ckj9EA3 z2g_zptTth*Ha=YDEUPxTNQtg96Pu&Bz<9(M=?8_FO)ge?UOpus@Bo`lE?%+)Nr~TE zq{I@SBdkBr5m2%LqohH0&g)eS$Gm^tfu6Orx=O~b~utbr6A z=^~OK=A~p#y%r6a3K_2lPW*!CUO>NJi#9y2Bf0{ljR$-fm(yq-vo;+mA=WCDjzZ9!y{ zeenUYEyaeW-5W`!lj7n7L}vmfx2HNaIBgj47vqJot$Kkmm79r_7R+xT)Qu^OZBKlg-3r8OgzUvDt}K{3lw+BgPAlwQLtoo=Fx@o-zE95mTB* z2&|aelqzuIWasnpg8Bh9brVdf7yT1kiP<9P(2`dm0zdKXK9Z>EnkFoSQ8pp<*TFwV zQs%>?(3D4m9g&n8Az4jXA7q+}TBixwh%q~ev?h1}IYxF7t3xQkaRZTlAJlZ*)mjAV zyI^jsO-QR&+&-r=vb8`+tyX+%6za2TB0g&xhWF(VtFp`oOBO7hK~9aAAkHCP5lrYH zrC)cInU3{nsfSogq%9HcY=%m|1{m56v!7_mcg1eQa?6wam~BbTnr((=ep_NQx6M7G zncbGq%xsHqCfgL>Qib{u(fup~5tfAXk!{N4cI-|E4~k&p1+GZfed;?-V$(9RQfuhx z3Xybyq6VgnlQ^!ZeuQ&d>yTDx!EIV7zUFLCe9d>jw>=m(x2hQBe;ms8y_cRV(Q#Y= z_5BlC@XbANR_cjv;(bKtZYTMpoC#1(PBk(y7>dLF#H9FI6si$WQ3$ah_)E(a^K>gF z^EM)x1M4kpK+~6WX`MUfBo>ubTLR}Vt}ouzxjx^`SeN9G{HbOfg^1T#2~5&tu(8n* zMNvLb+G-Uh2sU;6{t}=E6+=60A{`C#==OR$k^b2c*=x01oR*sC%rUyGl99{iv*TaB zG`r&aX-hk{y57AI$G&tqxXM_e@n*W6pUNr48927e?c$^!)%)h8Th(0`C*7=YQg4`( z{vJ-M;-p_GaaT>U-$eFboRrnc5Bt`KKBUKKv=_-CC6Cxx`wxE$CVmfS+l|h=f~bJ* zBq!HREN)X)J$IUo(I2HIYIrqqR0o2c1{>N!>HXCUzgXOfwAgw5~gK1KhtMilv$B<)72cgfnHL3 z<5uX@aGsd||2L*j+LIQU&vMMaGyN1+Fl)FaqwO6 z{uCX&g@0jl^{~?4qfz&gR5!Hk?*FcPZ?*q>PuzS}PYge4&|NjSGXn7K7e|*;PU>_= ztQGA-V|(V{TAGek|3YiJQVu^ZHECl9z%{er2G>(Xm~6{ZNzYee&4TZO0VL3x-;T95Z1n? z0YlBRZu@{n<~kX3ZdG*Ra8es8$_BgFLaZv#u22Dvh*$VoRg9NW{gHY`T8cOo=Q-p~ zMEGnd(>ww~T^A8*6ZZF0l&b~$<)ABTaCP|*elumXu zGn(XIpUX&YO}fk^+B=3@iFoMpjef;mZ+ zh#$_3%c1Mcct5d5`{~w$QCk}46c5hKaMKLwer7Pkj7SD|;jT`%Wk%7i&KcH{GZ$v2 z3EKt3Z1dSKAIx_#>Uw87dwR{Aj--=U3oG@H#l;EM+%Pj~)-3rXGqJblI-ws96jsp< zbZ)o{OV0QzRQ_(Yf;8bdA!YXSa)BqxoK`eYLHfxN!$v(B;vP~fpdLUBCZHH%Ce4|3 z3DtauNw`1cLuHrg`uCl*kyb{nN4ij0^H__!KqHJ0l3kjuFa~V)iNB5%3f&pq#(_bw zFcwa7^HU%@w-pYy-y=|3@iBoTeS~}7u~A@8lKdB7YSJN4)R(YApoacdfsE1g^7?F< zxBaD0%Nl1M*Tx*Hx7Ul`gO2zk} z^5cM;@$|s>po3~h3RzB%@c5v<{Jb?)6}47k^{{(-GUldSjpUBQ8UUS19M(%I5UR8v z3wIEUICO>;iUgP}QjO*`DC30%2p{mztJGGyPY-m})3mF6?IQ()Ge$@h48m9;Ww2s8 zS@px%Q=L)dBEf{ld&#ARDUISq9~){y!VljWl_Urv`crsxOn zQCU|WSN9!;H+ojR2!^>1AS7lUt`nV)V?XKEs=gkv>Tv48Z`I-4f}US!ajr?&EFlIK z?+HJVjDFgsn_Ig^rosPfaJFX0^_|&25P#Ijw{FMmv5C6lr=OW+!fp50HaFcv)7bm@g#q&@dC-n#H=NW{T5V8pS0`|*K5l;F6 z@n0c+CQw%MiA>5XB%XU0q2jYChYkTQ|U3F z@AJO^nl)QNuWGo*y;Itb+KCJx1WCuVm=eF2#M8+INwR{r!!<|*P-}ED{+xczs4hy zmlK^Bu1dq2o!}&v=zJTvkKI<%d7<{{&I|WGedQ&E;*+n~_G;U$|DmkGa#(II8Ci2! zenI_hF3C}8`rBNRt`SC)m2PXjsNT;#Ae3<93ak)`uuhkSSR`-b9 zgw$CJZeyiZg_ZuSlwM(|72h91)La?ttaQAS$3f6<6|Q(h_bBnp*(0wVIV|r}Ab|+6MS=lKB8D-K&WF9Fx1NM~hkR$FH^~3yN17q*npwdj{+P zoytMj4V>|ro>_P}(TE+U!D$*a#v`0LC=(1&HLJM%tf_f1C;b@Uq>#E9j9O;emxYl= zaMI#o+1gwT*}Q40;btsAxwsdmU0R4g7d?;P-!IO+L_ z3msdip25||e>0q#cZ8;*&c(}hy3FB7ojbJCLVBthRB!)=pE%famZZRWLk{>RU6aU^v!rZ=#5 zOzaG`{m`~YW?M#jGB6ZTe`6GSV`uQFtTAN>^WE}T13jqRA`?%`tZkhRFyD;BYc`pa zCWJX0WU$W}EA+X_I*gk06aK9+q zO#0T_@VJAqlGDT*QlNdNIt8V0lj#kcX``_dx(|qI}-EqGV7f$ z-)X&z@9WmyBD?u%##WQCym9;WZ#jJ4&#>4^1NYADhU!=svjuHpG8>t(k90ETOwZwm zl3Yct4p)MS1URcv)?FJ{f3-(*9deV5#AGq%<=J`Ujsj%%!*;o7c6KWz+*$xwWPze8p{wP!O-Y(aV#S3o4i z!xY%1$r}n??kSCyI%C6=j>gV7VVdVTXlq>LAd*O9H^4&sie z%3jmWHN6ahrh6FE`|cjLiQSRSXpsTRV&i&QZdjGMFpL_b()8>uC5JK#Fp(0!{72_psDbdX;0gbq^J#Cl} z`eH*@9N>PlBMFt;|E+QjD*uNZhsxtn`G2nThbt;QV%4#lEj6}V z2P=(lNRjFiC*U?Zk7tULyV&B~u0?NW&ps-XLrn9wv+?ohVV>!7E52oLC#Wx|_)0pB zS7rDS{@=j2#hvk2efx6o+vAAa-I6(E9%6dQEuNTnRK4V3K3n~ zSL3|gIC$-WMXLOkoF^S|USeitqk-<3qs0@^Co!@?W@__em;Dr9?R*0-CGyLD8Uvas z`&wPTXfJ)OZV!hZWDO}UoHeE^?E6}ATksSt;^VQ>;}OjrKau))7iPu_BZZO9w81$M z_RUt7;+k}<_vJ>mDBruRapFFv*yK%hPIlpx&11*xG-G@Be$M4KR+wJ@i+VX@rtqhF zPMX_a)c9M>)m)*}bGl9E9@ZW$1o@pp@-M&&(VfjkLMt?^>-?DSF}DZ()ulvh;DT|ZF}k!ZT~oor^-;T zEH8C()8XW1>A6Cq_jud6B7+y}uBoi9s4*EfE!kS+8C-Lr>Ktk-Rao^oYdu}3-KPC( zqm|@cQOWb+r48nyab8n{LCPa(=xDwu*2|dEoP~{Lb=kOqf2#A-w&QI@o?;^W9CfiK9OXx@K=$GmHy;8S z+j$&%MfEn(nYktr7lsX?I?D(=8N}tFv@STj8)+{d4(H*`xJig{4$K)=a;f*Pl;H?zg*Nw^p!j{}J;)jg zh_`1=1@T2dY|dJjQlMrXI$a3+o(+hF*_7+O0dZY6tuQ|z8gi;Ygz^46XF7;*s+~tniBukEF#b{Ng7g3m{ZQPz;aEN%_N7=NMsMs$VS4{Ux#< z?H5~e7p0W^TaM;_(UdpAz)H^sbg$9Aw(er3Edg;!UMUzi1omyqdxj~_mGjL>yBH}8 zp$!iw(hwFPOqQvon>4H&Hpt>FW>ZSoXO>M;on4Um#Dnnq!@f*ee8OA^QRd0w0dr0o zE1gz_iCQn(hm&RTteVFpiy4+mK7_rdSZA?hv69kHg-hsV2`lxhbTS0J*e^C)3X$(G z%D%r^JPas}BF@dXf#?m359d29tn`IUi|Ud6GnF!eI;v7RpgxwxZ}SU~|K;$$|rt4uRS*Geh6&t%hP?)BQUnLlG@Ja#to z#={pJZVvmpc^07z2BbSU!O8XUab_I0Gos?#7N(Tq+Z+j>iiC~f1ARQpG|f16q>tCc z`Zecol=)^|U#4!XUw0|Bf}f_5^7Q|6fuu6mJ$hD4s>WD^k<~a9B2S#v=qcydW$x9# zUT_d?z)frxxbTXvG{j72no_(LAsNpE8KU@_WQ#zaOTh8#C&7HP9w&o^{@ALOcy%(` zZxdGbj1%_sY!=4)*-L-vNkI2Uy+=Z=Bwzwo0zN#Z&J$9cq;Dm|!>5nh%`_qGyL)N@BNV+MICpSpT|WmaKX`>D&L}Y_hkR9j(wEOhoso`CaaGAR zH-8X1CckMY1eF7b zEhq(Vnkt+o&h23!cx+qL)l>E8?BDXA-J1b>3kANSL;VP9u}6#Uqw z>C4yBi-EB3E%ENsS=U#F%y_aM_T8>nkW0Ti?3)%k3W+U{SC911!_o9{A&bC6Vw(CS zlz@g63bUJr&x`$~lS^9td|y7J=`)kC?^Qp2w;DAh2FNkLpPj}OC3hzYuAH#1N&M-! z$t?Xlh;h02^Ph=OWnwOYDvwhe<$?+qsuVRZjFhj^bYA8KrqJQr1C3Nj!J4k+=-RMv zu0M7+{`3hIS3@n5(TrJs7t&wwdpcqvV6&eW7IbL(R>q9SQ*<=TZ)zPc&@adQ#NEN> zCxgU=LBU+_%C`ry(T~%V31CL4Rl)HB&GS@v0vN=ig5^k|Up9tI_9SD@;i@H^{c0Az zQMxo-Ae8LM#w`7;zhoCKqGVn$?BnyR%-Oq$G)}HUV~JD*o9z;25NQmEgkFXa$pR`F zpK{f|@|h7a0ZHhP9@|yB4mt>h_p+{z6Ot1KVS%# z($w*{WzOs)3{uArKc}^H1%3PQM>rGL^NKGJ62F?5527a|>L=ZDP0%+X?4k}0)W05E zfPE3yufCmLi>3(8Ee59x+JnCxaAilV>^NC`X3}U~(8q^!(42ks3lH&{ZrFhn;-ouX z)!%ss(fto_eVusrjv$&i>yP`+);$@=j29nRIhJ9?yY4ozgcDy_iGUS%-3?p9KDK^J zX#EoFFS&;&ojG*>=WUCZCN`Wq@Iy!bW2wJWeh6Jg{`|X5xv)Isruhp6V7?X)OUD9E z;BMgQpYMyg=Q>vWS$#SC)ZOBX_0!l}?-swPPb+>9kD7EkLUtmoJh#4l{kcjc5b`GC zEU)X9>P*CDBji2A#lByR5?k(%5npcT=fB5GC^g}K)+&4ooU(8AAr3;E3hAU8+aG^0QfubDezC=1n@QR9q=P?83+OV{X`cBBm^o>EhE5zM7oO%^^1uf!svK;}I?XV2kWKy(Y+rc6Y`Nuh&7| z#YEQ*99x3F23U%b2AY7cfpN?5Y#I2?T@VwOLk#hdi`c)$V_TxA{|Gsbr^`LSIUrwr V#a$?V>>j^$ecJz*|ClYh{{xJeGN}Ln delta 16270 zcmb_@30PD|ws760H)x<)R5qa(l%)Y#TyUjr;HFs=jZ2I%32sSiG!iulX4Kn?F_=}o zPR58yNHiIYi2@EYnrJYZeUc2VS%{+I#MlanDHQEXchmPjbpa(a^WOK~_kO&m*X#0@rxfW8DYG(1Po~Sx}3^kEaJ@yDv*8+SBP__=K z$25i%hfImFQ!?S;k|d4=(hQ#EF;#>gF+GLMH=C8k`if{f)kpDo1EIOf!_;N;(X81_ zp?oE!M~#8PeY7c(!B2Y_+|u3K<5$pA8-Q+|@G_kQ3@-L4fkD*(22(wny8A`e+uNWE zDyx?vbq=tXcD3C0VDYxP7<-7!;MZbg9gE96EI!_SZ*gQ9i|+cC2MRAa0 zupaQ?MOiW)?Pu^4K9q`|m4ZN3A$_XSf!-hMW;oJ37MiR4CN8G0IVH?zhs>@6l_5l_ zPrfx_ZX&2K0w5EBjCKK}Rq%Z(r1tJdw+iDgu*N9t`WkosZxwh~|sz(#dmk#v?vxWeiOvsl-S^j$8xPInABklYe47vdBd+FH+8&SazBVQ`2j%vFpWM`Na^ z;>h5lnPQSI!ba_BmlEwz# z94P;1SkQp-Bq$#wvram=!#ab%l~`MsE1<6Y7*Q#a0JwiymBcc*Q4&t5MyAi~F6~-7 zSr2-m@%w(gF_WWemH2g$C?a|QH8a@pCP_$8r|4)bKt*bwvZFw!#7~OC1L}Of)*DdF z7?D63EG9jtz%^bn?U~!Niow|uO9rWT+6N+ad1F-Z_BsV;F;KNJ_E32~(fCn+L@|t6 zr(PMsMcVJRtFxJp4_S?z+Zk0=U14zSDVN*_{4a<`WHD_3A4I*Qz|VRue3IKqIt(4q zq1PVmX-l^)-7co;nUm4wgs@&F{D9Z;AL#xA z==KXj=w>tqalB9$QT(r@HGUnCJ|(83Q(~6x)Qdpe@q!pU?M?^j|FMJD{o%Kr8RyM0wZ`D&-DH6rX%;(X*(CQ zkH+VGsim2Ay;0RMIW(qLflZRFUUF}j6vo8j#KI(7G>q2k-XU$0`%!7H`aShq*60=% z@0D2GE*U_A77=Cavc@*UbjciIqw(aPY&(^mT^0)8OnpNc1(xUP$*|umCh$6Ri$ZLN zBg26dc#ueq{N6RvPK^vnJ>Q}?s5k~_eUl5RRbbS2asyMmt~X0KOJ`c!~c@Gj~{ zk=lnSeFo&e2QL%^`6R&8uHw?V;`&lp;QAJ|ah%0OfvteTJ(eVcbN>``MUcWgw3#;3 zKeA>E9xOCzhfc34`fI~r2fBX9@x&25C%NzQQzmoyPT;?P$qRHw5msIrlOF8cKA;>% z4VU-mIr(d;N&@DG2eNT1_GiBA`AF8cZ^y$aGoO4wYy*@lF#ud+{$ zhv8Y%Bf03sO_NF*K{T{yH&l^L6S))`rmRj9)_WJohIQsV>4 z!n>&vD8+lWxAjrE_2A#NRv#pG{Z|*=fmQ~TX*+4v$F4&+%SZgox3I<>&RD2`fl+cO zsi04aT{4k@F%aK%`9M@*v~7p0*EhAXz4o{h>@yAQF%BRfU^u`m01_8H0_jG8mjTF% z`6{GwusZhJa63DL(i1~2gu;;k69Ik!e?Jq_c>rWVdJAk~iI>c^y?`z9GN79`i*vZR zvP^Cam(A5od86clxamZS9sd9Gf@l|Vby12{2MlH9!u`5L{&E{KJY$pGwca|b1-Cmk z0iNz7_$7zr9^Z38jNN$Gp$nq8?dho*+`S?j!-7>wJzRkstmx;*7tgx3mrX&YWkpdOOp}E`HfO2r1u@ftwo`wK=BNoYe%pJgAqhgE zWjz_GSDgyn-YvPc-Wmvl%8KR}vfJku%_r<+%`Z|2)b_F>1VH2GypsD15hdkzEjb{$ zyFBws2|n)tGH{@T!CocL&3u>e9x@oApYxvFsdd)euGE8I@l`SK zh2IRHVvP_tZd2eUpK4zuR9oUv)k^LZQF1R6RS=Ur^;jl!)ap$m(*&A_9F*LTL2%gL zZjZ0D3r#lLR1gekJbGhtp$eS(H7}7>c~H-343ay_|Np)HpD+zOtQcvbMQyxsyK zH*vEQASEuB1ac(!I|kNw8sIWOf51mfw;SMjfSmx2lV4DEkdhdCADA`?5RXAhO#d{b z=K#o7VI)lSuy0!Twp*Q=)Lh3xscWiOTvdSG@c=B3tz&wdJlI} zYE37lIpxf@kFyI_zH8sR)eV8*v%c}NCS({Q`@3u1LyC8Te%ON+gQ}LsOS>bARIrdw z)SVK?BIaa+I9az{%+p6XcJ)OIs&`oYf}cbSj!Ox^B$yF=$SfycFD*>J!~nKi`m85g?c+mQ#VC{d;dpwCgfN= z-GdAyWxN-}!w!J0Bp2&PX&$G!IHrO!-)h+j3oJ5UciN!cJf9FeD0LW(XGz%=Dx+`trET*oDsobQ(rMzp37E&9jp|d z8f}B9^rk3$IywOwUKA5xkJ%s6?08@B$;F?F`T@mj-WRgQOn_#ui^9q=RzTK@!r?Kq z0Vx%QupCm7DhhLQI6zdQ@FpNM{--4Tl2Zi82a+&uY#AV1B;mEO+X0y*2_wht0OYz~ z_-b4UAYb~0*zv|J1%6C4a2XI4g3FUqV4F+rliVLkHV9rR?Cv4{J^Xg;N#h#7P(J=q zX#cQZ_~-a>fY|(ke!^1`bL6W1F**ghru@Qz38bqZdj$Uk!o`a{!j6eHKpI4gv3@EBP5=a zv0;F1ma#E_ZRk!vNZMFx6`eLEi`R4?$|}4@0ntzWLPBv;0*jZ*^MHu4SjJ)iD-$(x zvjo8BiigUJmysq{z*tHKGnBAg=q`x~VDM(?Asd7>1|e=r9HVVl2)R?z_}T3=^M$C_ zX`R$g$?f-)fZ+;#Lxb>(4hnDWu^A_G8)_N+55Jz<0A@bSOG+3h`P5GhXWkpZ*+$un z8}^Z9^q8L-ox+WkO)S%=PRCB0{zp;oVBRZjk9>%lw7ETU#>pF226>rjMlPE#l-#Yp zTvJ5i1@YrLBm{P{0S0aw*y(iNSD zDZe{O>Ya_NMT0%KxYXiNg?u+~BS+!aeMV>nswJBSi{Jg3@N?;i$qdf%_gWWhr2R=C z$*pd(Mb8-EckXGX@FPCb*6;3wHT$<_MQ4J_z~w;xsxWI>!Cg=E7+~+~cW;%9P%B`c z-@Ux&Tj1CT{02a|_ICOF9wWyB$E5Taj08y^m#BRt{fBUI+L*MTJZxtIrRX#uzx$jg z0{G~kq&nc^nwK6=nZsH_IeV<%{k2dqeGCmp59_DL!HL^yurOpu1AAK0Lxi$}9W9kH zGIbfeNXEn9`-44WfzcRnx?3fbw7Pi-sMhaxcr^Rqv=KV~gC~Ov12LZT*rEKC$8kgh z41VKbxj9D^oy(M&u$=|5y!!e~j(kyh5r2eE2m|z}2PI8)F8iRj8u_?f$^v2p+w05Z zNSzP;SwKJo9aKXJ`O*lwPkSc}CdC4O%>HO#P6K#(4=IfSEYOn%5!aU@%jpiW2{uDa zEyCM8HV_u!7r-Cdxv2q=Yjy%44}#0Q zXEvEUq8)a4Wb%|-5H=qcHs7O%4xjc2@7yz7Md81Sv32Ew>+X1{yGQH|0vP=65fUy4 z?s<_xpwR#HsxA5SWx8gyJw8qHX%^hT8Gl4Gp-lbMK=j)EH1)387W*(Fr-% z>t|5mWNp24X?*d03TKIgwj9JXCPSNKTYoDWJ3Yf;lgP3GRpHKAs)XW^-_0wFE!SZ^ zJIJ}6SEhX1YS$O-u+pt(>{Qm7GGvTi8PXO84WgY<#q-Ljgx<BKe*K7u?y62Pn5mR#vSsbVvf9M-s zflMh}jseHQMDdba1%z|GG?$g1YZ_xfdNvE;3%;-FO;d6VDcqCLX0I;|+8CkDC!OmM zkFX7PFnVZ~;62{C7Ue=%JH}v%LHJ`I@k;$ikb0+rc+^sabKXa3oia1CdJenLE@OQ* zmmsq}-Ah3ZndSi72p4%{>$9OlYtLIQl-BM10Ti#7h@DKUfUOBYdE*4Wc*4|8U}B6M zy(>5^F!D=xb_HYBv|PBt;Iez~rpZbF$Rffhly_2EEoQWvMRXhuC(P!6l%$hMruD|L z2GGjO2=DhL7k%83AJNdUDWtT06Ju^2UU+861}_tSqGM0k+LYR+wMHt78jce9iKcM| zI5~$#+k9hyTn5p_4uqferPZ6b6fQ#^fcf6A0lJ8BvVC*!&=Jab)>CfM7RKOl7!?~|m{Qx@osKLtCvHJ}nu3u=rUFzp5x z3*8QrAZ}tdVv!cQH=Y!_H-uM;q^#29zz(z#AE%$kZQ2bOQ;ZbeJab1*%rcqc$1$d~=VeJ&95s_|o#h?l*`!%Z; zM%-|Y@hb3iJJr!fg^IyCgSEApkh#`R=HI9!=k?Mc6b4lg8s}Q6F$b-xGpJhKDdiyZ ztIi1=O6Omb&%OJtobI*qmk|D@hl~?Z5z)}Jl5p$@c@DgSM)nE}=GllQ+C-T)a>{Lb zE|eS0(L#^=9v=fsY%J^_df;SWf%Wc!d(WWMd(JT&=rEA&2%z_L1Td3qitUszgX7J$ zd=n39iQGyhe#51-x36Tje|eK%$z+`b)w6*7WvkYlpP{rC?Aiw0)c!&5T;Woz8RW-s<=$G=Cl$94af& z!`v|CHCXdzb~>qvwFSRAd1{PiL~th^Om_8OIu+Fcom9Y#f_f*J`~AC|cxND)`!BuU z$%kBSIRc9RsU?GYNbb2u5e~RL6u5C@@yIE6mLxOmx2HIDh722p-+vd}mjr2~()X>-kN_<4uL!QW8kM5>Bh*Ar~i=c70xs@KVUfKt2L$M?)GW3-_QuvLtdU z+Zm-G!ewx9CGoiU7DyM~Ctc`m>EMbC-|~~;2!hc5Pu_v+KkMv`J|y>;CWOcP`j%5* znh0^BPl&$RGuZ?p^v45mm7A2)9K=x-gJ4EQ@J)0gmALH?EVb&GsS3<1lxsw^XE>D7Kwa+6DOTHr?C1WRv`}%{DP^X0>Y~c;a#2d29T`u16 zvkT5?0Ke#Ra93Pa++{GuOJ1V!dqLxAS9x4IZoq1fwxN_U%@JH!1)1;hTtrhTrZq5k zH46>}a;j|3oYjJcIk~BrRM6wTiwH5omapLRQOeIwa#Psvg3Ns`D3lvSx==wE$wQ%w zzt#dW%X#CcF5XBwh8Rbd`Zv(PuYDT03XM1 zY1SQ1fzkF438N|HZNTVxnbDN;Gr;JFo_>Ss^=!h{_{dm=6PbELWXW9wUhGY|(wz#t z!b#n(kO38{d!4=td~#*GmU$E0{%_9UPHEB;1?^4+KVari zva3S)F3%k&-OC6$U(Gcq6IRMA>j*Pjt^KULDkhZ;ZyidOwqRgtHG~W0z|N}pLMDUG zR&)ew-?fIfCUUoqc=AfyUFw>S&m%)c^;R0IXle`}?4hqGx6|~|0!mcte|1thJFS+WbI zul4J^);uavfmI3;3aLDbo8Rb4+kXoFvn3Zop-%^wwto}1yn%06*}~^0Z{pDP(+=2> zo|zfTwqIIJ!jwe?-qr;L@nbYCD31Yde(610CAnw>z}TxARBlAB9y|)jGT) zJ#TpVYa%L}l=mY1Cv6uLkkMs3rIEj!p)y~wjyi*q%FgmBd@D*he!a=TC!re`94J|N zhH3waUrlAcVfCGT&T2ddosIe`57eW6sx&G3o#@=;@YZj1H65SE4H1KngCyke=w?B? zR{Lhhr-M~cHbhh&hrHt0EGqLkE9vr5>(T*3XTg7W^!no5mGn&ZOD;eD6p>*;fpn|nAen}#C1eVcVOlK@5ZyYgVq)H~ z@_}NE1}1Xd%MYSt6$}9X6Y#N39su6G@L(?^G5-TbN?g4JegaKw=xd(`?TIb|{|CBA zg_$y26nR(!i4|uwh82cQ(b|*jVK8MjS^K9M#@C~wSzb14s8GN+Yb5L zO!$`3SXBHR1UDLa{|c|kjA+;?F=AptNnRIP71XKKo`77)SMOd4K|8K6=y?F9mcsXY z`O>cAWfXqJYq?HA`bS7^LzlL-jq{|__AJU*0 z8(>oa8yb)aSP;R4jKoOc%rI>*Eyu(78F;SaM@>T2@Kmy~zRgO;zp!z5Yu}Y4uyXi# zdTIL95mQFkGDgI-w-XhCmH8-X5 zFu7VE(<$0J3>*ByLy1}ZV1%ai1}9WbzYCz7Q4^KplXuAdL3aOAD7ml6+cI6_paIeS zzWQ)3tORvR6X=e~!LcG0LT4k5e%@;Zj7V#DlM^x=g7otkkGvx8)`_67D zP^1p5<+x0I5zMgCTfeMAjfO%)(H(OLwFg@E+$_oaWqkIL?e-Hl0_itz`BsMK#Wo|n z0d_^?K<5&1S@?~SvSrCqGLiWnI>ITYuu|+?iMz)hS9B&}&E2+gdv37*N@-wO5v_yil z&`mIPSytt>v!)Y(lYAbgze>G}OGaN|YMFma!Pw;4WPDVDOCvKklh zxIW^(<=F`r*mF;UgeXB*6be%6!F5yHiRX@mmIYoi*Ya-tNxyqOg>$@cXXzanHudfj zbruRw{s2z(<&CaPyD^X-;IcJE;qYoLyli08J7#vUZ*$q(FuXXR;?Dm6{Ue1{e6psc zS!~sR(Xiq1?P5m8AL?hoD_+W|E{=ko;k_1MmQgu%a3Lh0eHpJq;Er9q^!wUa#kt zRPDU$Z*T!i>Ei|r(nv5ae2lTrS&NdcH$P-2$GJ>frIqdsq7(S$>1(L$Bhct<1JjX5 zF&!JIps_zao|&&+gOWaiv)_2mDQe21sqOdPT|cB;4Yez+ji>s{P)e7R%HCx;^!i?a&iqIvh-3J|AWe7u6HO%LlHKN|2ye zP4Kn66Np}yw_vF8g1G2-WnC*Ax_%93c%V}4R&mI2i(T7M60GfbQTuLZkakmky~wuh z7Fo2pV9+T_AL)3ms#VnJVyOG(F!k`BLQkmn4RX9ZF61ag9u@r!=$AiQuBE=#))Ov@zPTrRs|Y3df7c=!lMNqVy(vWVy*cx4%ER zI~wTqx|hfMUR0n)?SQf0QbifRXn=EE`K2+{?~?|yaqoZ85XlW&dmHxovVrX;_O;VB z#uaU>>z_m?*2Qvkhn1l_D(O6X(70%#!sFp<78XSQcuI`XWE52~9oo3pK(D3k+Sr#1 zf_|JKYBToKM+^0-;XG>VeQn+En-#r2CFN>!BzGMY>XUbrA4pa?BuK1+m6Gfz`(5pKX${p4}H8}7# zAektW%#=wU^1}Cw@5Lb9gFram^Ncs%^Q`BM`tQZiX*TXHYi-jo?wy7~a@|+GP@1tQ zW>^0G`Fk7UJx|MZv-vg1JgFHC`(D&!eA1x^ojZ@&_NJBTpj7dmjbiDKMy^Kgki60( zQat5_Gh0*jydOlB?xfu5b21@n6iS}Z{DT^0H zhP@qX7TQ?}3#28;|4|E7jb7xpD2S#d`1NSq3b1d{;d%?W6IdKG$Ycu` z;NG=;zKb$uWg&f@Xw?1YqK%@9G2Viym(eY6uyl>vz-Q)w&x*xmA^mD1zQmP*ZS zrc;MCm(-J22>o+-wiC%ds-!}bdc7s&I;)*0Cg7K5A+>wv??HgF=laT@f%H!RB^6X^ zax;^f+Kf{9)6N)pkGkkMxb3!c;8%9H2g4Bv(hhU(mCs3ama@A_DgshtngdfAXz+nk zS8~~?XIv#!DD@p@aLIQv_LeiKq}dfz@(sxP0qp!p*w9^y)COSk z$TWDJI2G~gvC|;~g+Ib?$kL`F^#=G*2rvc8dSlK0Nb~ns0Fu#RV2kCY0YbC$5Dq>o z-!B_x%MboawcKReGj+(W*b3qxxRI5;*_G~v6-skJGp!#B`czc&y+0FK>Qs?Kq?Z;} z#RPg487!DRJOXw(vJ5z-0XZJjP!e zB7a1Q7hM*v!8Hde3*ZbM`q%0={@f9unh7nM8c2&TTi}{U|A2$3-eb*aYHgsZlbS9y z#5%UQ;$zfY6UEX*A^ms5!yDn38n=f>cMKkb$nB5agVeZD%MG)>Mxt4`NbFhC*2qwTSF;yPaKW=u4^=J_`A zQp2ip967SQv7EwRisP$xgAtXI8Vaj(IY=2Dz@&6S*muo*&1tSu7KMRJ3o~VvQF^oEGRP6sw^5!T-;is$ z_=HL6WK$$ffeh5Yw+71kD2Zqd!Ux1xY<&E{b2>^ z+6XDR{C@iOg8;vK6#S45exoSRTdC@u)}V7#HN7i5ztTFyNmWzXP!7-0Xo0G(w052) z|3Q@M;v>Y|$&JHcn6nHEH!38`>~UZ2@w*>{4f>&$dycb;Z$YLO;njKj1A68o_5BNw z`oaR??)!bLO1*3(7D(>>xx|vzO);zLC zzv|eNmM=;!OsV5?9Pn+;8 zRND&GUUQr z^^4Knj~_VSHEGa;HecwT^v|~L%MLp>2db4U)lVv%eH!gA=s8((>XFYM3u@al^w_QQ zt4H+&7MfiFpFMbf4(z+p%)94u0Cz8jpEbM=&yN2L=|xCQ%MX3CbRr!e3U#6bG^}APrz7z&HRaKq0_%fVlt*0G0wg2Ji&H9{?NxPp^bCt``8=2Cx(0b%3`4-UIjx zz!8As0G|Q;9iSP2F!KYX7XhvS{049fpa*~fEouOQ0R{oY0t^F41;_>%2Veon2PguV zriOnbd{VqyaIT3y^y7P`}RQ?KVfS{ z^n8RCEndBN;p)YU(xGU^>iG*F(XU!Qf0cd7qYopLw`>LEmpr;^_51}(mMvMm2I|=6 zuUw>mX#V5NRwFcJ@$wZb*YxKQ%E-*h9yx0Cn4Gbbt$Fzc9O>mo#Yy2WYa&t*9P%PG z2Yg)qwY52GujR{mJLG9r-Ga;D03rjS3djrd*P4ajmUpu?@ID4I!-UWk68kwkn2|GM z%i-s6@RSBJ!-WNp`RT}Y!h)5d+) z9KFyAgcv1oreG2I83lSqU<%*|+oKjioC2_XG1w8njE6wg0Dl1Z3}E8JU>i&1X)ujK g4pafoaVvl%AruY<9}h4bAOU1fTbm->yLQC?12F`S Date: Tue, 29 Mar 2022 14:59:55 +0200 Subject: [PATCH 31/32] docs(legacy/firmware): changelog for 1.11.1 --- legacy/firmware/.changelog.d/1018.changed | 1 - .../firmware/.changelog.d/1018.incompatible | 1 - legacy/firmware/.changelog.d/1880.added | 1 - legacy/firmware/.changelog.d/2031.added | 1 - legacy/firmware/.changelog.d/2036.fixed | 1 - legacy/firmware/.changelog.d/2077.added | 1 - legacy/firmware/.changelog.d/2100.added | 1 - legacy/firmware/.changelog.d/2107.fixed | 1 - legacy/firmware/.changelog.d/2115.added | 1 - legacy/firmware/.changelog.d/2115.removed | 1 - legacy/firmware/.changelog.d/2144.added | 1 - legacy/firmware/.changelog.d/2181.removed | 1 - legacy/firmware/.changelog.d/2239.added | 1 - legacy/firmware/.changelog.d/noissue.security | 1 - .../firmware/.changelog.d/noissue.security.1 | 1 - .../firmware/.changelog.d/noissue.security.2 | 1 - legacy/firmware/CHANGELOG.md | 44 +++++++++++++++++++ 17 files changed, 44 insertions(+), 16 deletions(-) delete mode 100644 legacy/firmware/.changelog.d/1018.changed delete mode 100644 legacy/firmware/.changelog.d/1018.incompatible delete mode 100644 legacy/firmware/.changelog.d/1880.added delete mode 100644 legacy/firmware/.changelog.d/2031.added delete mode 100644 legacy/firmware/.changelog.d/2036.fixed delete mode 100644 legacy/firmware/.changelog.d/2077.added delete mode 100644 legacy/firmware/.changelog.d/2100.added delete mode 100644 legacy/firmware/.changelog.d/2107.fixed delete mode 100644 legacy/firmware/.changelog.d/2115.added delete mode 100644 legacy/firmware/.changelog.d/2115.removed delete mode 100644 legacy/firmware/.changelog.d/2144.added delete mode 100644 legacy/firmware/.changelog.d/2181.removed delete mode 100644 legacy/firmware/.changelog.d/2239.added delete mode 100644 legacy/firmware/.changelog.d/noissue.security delete mode 100644 legacy/firmware/.changelog.d/noissue.security.1 delete mode 100644 legacy/firmware/.changelog.d/noissue.security.2 diff --git a/legacy/firmware/.changelog.d/1018.changed b/legacy/firmware/.changelog.d/1018.changed deleted file mode 100644 index 018e42bd4..000000000 --- a/legacy/firmware/.changelog.d/1018.changed +++ /dev/null @@ -1 +0,0 @@ -Ensure input's script type and path match the scriptPubKey. diff --git a/legacy/firmware/.changelog.d/1018.incompatible b/legacy/firmware/.changelog.d/1018.incompatible deleted file mode 100644 index d0b3118eb..000000000 --- a/legacy/firmware/.changelog.d/1018.incompatible +++ /dev/null @@ -1 +0,0 @@ -Trezor will refuse to sign UTXOs that do not match the provided derivation path (e.g., transactions belonging to a different wallet, or synthetic transaction inputs). diff --git a/legacy/firmware/.changelog.d/1880.added b/legacy/firmware/.changelog.d/1880.added deleted file mode 100644 index 69c3a8fca..000000000 --- a/legacy/firmware/.changelog.d/1880.added +++ /dev/null @@ -1 +0,0 @@ -Show "signature is valid" dialog when VerifyMessage succeeds. diff --git a/legacy/firmware/.changelog.d/2031.added b/legacy/firmware/.changelog.d/2031.added deleted file mode 100644 index 5255aee47..000000000 --- a/legacy/firmware/.changelog.d/2031.added +++ /dev/null @@ -1 +0,0 @@ -Support Zcash version 5 transaction format. diff --git a/legacy/firmware/.changelog.d/2036.fixed b/legacy/firmware/.changelog.d/2036.fixed deleted file mode 100644 index c402937a7..000000000 --- a/legacy/firmware/.changelog.d/2036.fixed +++ /dev/null @@ -1 +0,0 @@ -Fix domain-only EIP-712 hashes (i.e. when `primaryType`=`EIP712Domain`) diff --git a/legacy/firmware/.changelog.d/2077.added b/legacy/firmware/.changelog.d/2077.added deleted file mode 100644 index 6ca321ffa..000000000 --- a/legacy/firmware/.changelog.d/2077.added +++ /dev/null @@ -1 +0,0 @@ -Add extra check for Taproot scripts validity diff --git a/legacy/firmware/.changelog.d/2100.added b/legacy/firmware/.changelog.d/2100.added deleted file mode 100644 index 4502ea3ef..000000000 --- a/legacy/firmware/.changelog.d/2100.added +++ /dev/null @@ -1 +0,0 @@ -Support Electrum signatures in VerifyMessage. diff --git a/legacy/firmware/.changelog.d/2107.fixed b/legacy/firmware/.changelog.d/2107.fixed deleted file mode 100644 index 0f0cf66f9..000000000 --- a/legacy/firmware/.changelog.d/2107.fixed +++ /dev/null @@ -1 +0,0 @@ -Fix legacy technical debt in USB handling (readability and FSM unwanted states). diff --git a/legacy/firmware/.changelog.d/2115.added b/legacy/firmware/.changelog.d/2115.added deleted file mode 100644 index 34ed07dd5..000000000 --- a/legacy/firmware/.changelog.d/2115.added +++ /dev/null @@ -1 +0,0 @@ -\[emulator] Added support for `DebugLinkReseedRandom`. diff --git a/legacy/firmware/.changelog.d/2115.removed b/legacy/firmware/.changelog.d/2115.removed deleted file mode 100644 index 460d39e92..000000000 --- a/legacy/firmware/.changelog.d/2115.removed +++ /dev/null @@ -1 +0,0 @@ -\[emulator] Removed support for /dev/urandom or custom entropy source. diff --git a/legacy/firmware/.changelog.d/2144.added b/legacy/firmware/.changelog.d/2144.added deleted file mode 100644 index d89148122..000000000 --- a/legacy/firmware/.changelog.d/2144.added +++ /dev/null @@ -1 +0,0 @@ -Support unverified external inputs. diff --git a/legacy/firmware/.changelog.d/2181.removed b/legacy/firmware/.changelog.d/2181.removed deleted file mode 100644 index 5a50859e1..000000000 --- a/legacy/firmware/.changelog.d/2181.removed +++ /dev/null @@ -1 +0,0 @@ -GAME, NIX and POLIS support diff --git a/legacy/firmware/.changelog.d/2239.added b/legacy/firmware/.changelog.d/2239.added deleted file mode 100644 index 42f72dcd5..000000000 --- a/legacy/firmware/.changelog.d/2239.added +++ /dev/null @@ -1 +0,0 @@ -Add firmware hashing functionality. diff --git a/legacy/firmware/.changelog.d/noissue.security b/legacy/firmware/.changelog.d/noissue.security deleted file mode 100644 index 71a0f5aa8..000000000 --- a/legacy/firmware/.changelog.d/noissue.security +++ /dev/null @@ -1 +0,0 @@ -Strict path validations for altcoins. diff --git a/legacy/firmware/.changelog.d/noissue.security.1 b/legacy/firmware/.changelog.d/noissue.security.1 deleted file mode 100644 index 20b941c5e..000000000 --- a/legacy/firmware/.changelog.d/noissue.security.1 +++ /dev/null @@ -1 +0,0 @@ -Make Bitcoin path checks as strict as in Trezor T. diff --git a/legacy/firmware/.changelog.d/noissue.security.2 b/legacy/firmware/.changelog.d/noissue.security.2 deleted file mode 100644 index 893108612..000000000 --- a/legacy/firmware/.changelog.d/noissue.security.2 +++ /dev/null @@ -1 +0,0 @@ -Fix soft-lock bypass vulnerability. diff --git a/legacy/firmware/CHANGELOG.md b/legacy/firmware/CHANGELOG.md index f6445625b..b7b99f84c 100644 --- a/legacy/firmware/CHANGELOG.md +++ b/legacy/firmware/CHANGELOG.md @@ -4,6 +4,39 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## 1.11.1 [18th May 2022] + +### Added +- Show "signature is valid" dialog when VerifyMessage succeeds. [#1880] +- Add extra check for Taproot scripts validity. [#2077] +- Support Electrum signatures in VerifyMessage. [#2100] +- \[emulator] Added support for `DebugLinkReseedRandom`. [#2115] +- Support unverified external inputs. [#2144] +- Support Zcash version 5 transaction format. [#2031] +- Add firmware hashing functionality. [#2239] + +### Changed +- Ensure input's script type and path match the scriptPubKey. [#1018] +- Included bootloader 1.11.0. + +### Removed +- \[emulator] Removed support for /dev/urandom or custom entropy source. [#2115] +- GAME, NIX and POLIS support. [#2181] + +### Fixed +- Fix domain-only EIP-712 hashes (i.e. when `primaryType`=`EIP712Domain`). [#2036] +- Fix legacy technical debt in USB handling (readability and FSM unwanted states). [#2107] + +### Security +- Strict path validations for altcoins. +- Fix soft-lock bypass vulnerability. +- Make Bitcoin path checks as strict as in Trezor T. + +### Incompatible changes +- Trezor will refuse to sign UTXOs that do not match the provided derivation path (e.g., transactions belonging to a different wallet, or synthetic transaction inputs). [#1018] + + ## 1.10.5 [19th January 2022] ### Added @@ -459,6 +492,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [#131]: https://github.com/trezor/trezor-firmware/pull/131 [#965]: https://github.com/trezor/trezor-firmware/pull/965 +[#1018]: https://github.com/trezor/trezor-firmware/pull/1018 [#1030]: https://github.com/trezor/trezor-firmware/pull/1030 [#1098]: https://github.com/trezor/trezor-firmware/pull/1098 [#1105]: https://github.com/trezor/trezor-firmware/pull/1105 @@ -497,5 +531,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [#1854]: https://github.com/trezor/trezor-firmware/pull/1854 [#1857]: https://github.com/trezor/trezor-firmware/pull/1857 [#1872]: https://github.com/trezor/trezor-firmware/pull/1872 +[#1880]: https://github.com/trezor/trezor-firmware/pull/1880 [#1897]: https://github.com/trezor/trezor-firmware/pull/1897 [#1985]: https://github.com/trezor/trezor-firmware/pull/1985 +[#2031]: https://github.com/trezor/trezor-firmware/pull/2031 +[#2036]: https://github.com/trezor/trezor-firmware/pull/2036 +[#2077]: https://github.com/trezor/trezor-firmware/pull/2077 +[#2100]: https://github.com/trezor/trezor-firmware/pull/2100 +[#2107]: https://github.com/trezor/trezor-firmware/pull/2107 +[#2115]: https://github.com/trezor/trezor-firmware/pull/2115 +[#2144]: https://github.com/trezor/trezor-firmware/pull/2144 +[#2181]: https://github.com/trezor/trezor-firmware/pull/2181 +[#2239]: https://github.com/trezor/trezor-firmware/pull/2239 From 85a26d2c9593bcdf858c2d718d79951ca927a0c3 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Tue, 29 Mar 2022 15:04:41 +0200 Subject: [PATCH 32/32] docs(core): changelog for 2.5.1 --- core/.changelog.d/1018.changed | 1 - core/.changelog.d/1018.incompatible | 1 - core/.changelog.d/1430.added | 1 - core/.changelog.d/1751.changed | 1 - core/.changelog.d/1751.changed.1 | 1 - core/.changelog.d/1880.added | 1 - core/.changelog.d/1939.changed | 1 - core/.changelog.d/1944.added | 1 - core/.changelog.d/2020.fixed | 1 - core/.changelog.d/2034.fixed | 1 - core/.changelog.d/2036.fixed | 1 - core/.changelog.d/2077.added | 1 - core/.changelog.d/2100.added | 1 - core/.changelog.d/2114.added | 1 - core/.changelog.d/2135.changed | 1 - core/.changelog.d/2144.added | 1 - core/.changelog.d/2166.added | 1 - core/.changelog.d/2167.fixed | 1 - core/.changelog.d/2181.removed | 1 - core/.changelog.d/2239.added | 1 - core/.changelog.d/noissue.security | 1 - core/CHANGELOG.md | 55 +++++++++++++++++++++++++++++ 22 files changed, 55 insertions(+), 21 deletions(-) delete mode 100644 core/.changelog.d/1018.changed delete mode 100644 core/.changelog.d/1018.incompatible delete mode 100644 core/.changelog.d/1430.added delete mode 100644 core/.changelog.d/1751.changed delete mode 100644 core/.changelog.d/1751.changed.1 delete mode 100644 core/.changelog.d/1880.added delete mode 100644 core/.changelog.d/1939.changed delete mode 100644 core/.changelog.d/1944.added delete mode 100644 core/.changelog.d/2020.fixed delete mode 100644 core/.changelog.d/2034.fixed delete mode 100644 core/.changelog.d/2036.fixed delete mode 100644 core/.changelog.d/2077.added delete mode 100644 core/.changelog.d/2100.added delete mode 100644 core/.changelog.d/2114.added delete mode 100644 core/.changelog.d/2135.changed delete mode 100644 core/.changelog.d/2144.added delete mode 100644 core/.changelog.d/2166.added delete mode 100644 core/.changelog.d/2167.fixed delete mode 100644 core/.changelog.d/2181.removed delete mode 100644 core/.changelog.d/2239.added delete mode 100644 core/.changelog.d/noissue.security diff --git a/core/.changelog.d/1018.changed b/core/.changelog.d/1018.changed deleted file mode 100644 index 018e42bd4..000000000 --- a/core/.changelog.d/1018.changed +++ /dev/null @@ -1 +0,0 @@ -Ensure input's script type and path match the scriptPubKey. diff --git a/core/.changelog.d/1018.incompatible b/core/.changelog.d/1018.incompatible deleted file mode 100644 index d0b3118eb..000000000 --- a/core/.changelog.d/1018.incompatible +++ /dev/null @@ -1 +0,0 @@ -Trezor will refuse to sign UTXOs that do not match the provided derivation path (e.g., transactions belonging to a different wallet, or synthetic transaction inputs). diff --git a/core/.changelog.d/1430.added b/core/.changelog.d/1430.added deleted file mode 100644 index 37c633be7..000000000 --- a/core/.changelog.d/1430.added +++ /dev/null @@ -1 +0,0 @@ -Support Bitcoin payment requests. diff --git a/core/.changelog.d/1751.changed b/core/.changelog.d/1751.changed deleted file mode 100644 index bf07aa480..000000000 --- a/core/.changelog.d/1751.changed +++ /dev/null @@ -1 +0,0 @@ -Automatically choose best size and encoding for QR codes. diff --git a/core/.changelog.d/1751.changed.1 b/core/.changelog.d/1751.changed.1 deleted file mode 100644 index d0c1c088b..000000000 --- a/core/.changelog.d/1751.changed.1 +++ /dev/null @@ -1 +0,0 @@ -Bitcoin bech32 addresses are encoded in lower-case for QR codes. diff --git a/core/.changelog.d/1880.added b/core/.changelog.d/1880.added deleted file mode 100644 index 69c3a8fca..000000000 --- a/core/.changelog.d/1880.added +++ /dev/null @@ -1 +0,0 @@ -Show "signature is valid" dialog when VerifyMessage succeeds. diff --git a/core/.changelog.d/1939.changed b/core/.changelog.d/1939.changed deleted file mode 100644 index ae8d1734e..000000000 --- a/core/.changelog.d/1939.changed +++ /dev/null @@ -1 +0,0 @@ -Full type-checking for Python code (except Monero app) diff --git a/core/.changelog.d/1944.added b/core/.changelog.d/1944.added deleted file mode 100644 index 4ed3d34ef..000000000 --- a/core/.changelog.d/1944.added +++ /dev/null @@ -1 +0,0 @@ -Support ownership proofs for Taproot addresses. diff --git a/core/.changelog.d/2020.fixed b/core/.changelog.d/2020.fixed deleted file mode 100644 index 0e2d289ea..000000000 --- a/core/.changelog.d/2020.fixed +++ /dev/null @@ -1 +0,0 @@ -EIP-1559 transaction correctly show final Hold to Confirm screen. diff --git a/core/.changelog.d/2034.fixed b/core/.changelog.d/2034.fixed deleted file mode 100644 index d6f7b11e7..000000000 --- a/core/.changelog.d/2034.fixed +++ /dev/null @@ -1 +0,0 @@ -Fix sighash computation in proofs of ownership. diff --git a/core/.changelog.d/2036.fixed b/core/.changelog.d/2036.fixed deleted file mode 100644 index c402937a7..000000000 --- a/core/.changelog.d/2036.fixed +++ /dev/null @@ -1 +0,0 @@ -Fix domain-only EIP-712 hashes (i.e. when `primaryType`=`EIP712Domain`) diff --git a/core/.changelog.d/2077.added b/core/.changelog.d/2077.added deleted file mode 100644 index 6ca321ffa..000000000 --- a/core/.changelog.d/2077.added +++ /dev/null @@ -1 +0,0 @@ -Add extra check for Taproot scripts validity diff --git a/core/.changelog.d/2100.added b/core/.changelog.d/2100.added deleted file mode 100644 index 4502ea3ef..000000000 --- a/core/.changelog.d/2100.added +++ /dev/null @@ -1 +0,0 @@ -Support Electrum signatures in VerifyMessage. diff --git a/core/.changelog.d/2114.added b/core/.changelog.d/2114.added deleted file mode 100644 index 090c6333c..000000000 --- a/core/.changelog.d/2114.added +++ /dev/null @@ -1 +0,0 @@ -Support Cardano Alonzo-era transactions (Plutus) diff --git a/core/.changelog.d/2135.changed b/core/.changelog.d/2135.changed deleted file mode 100644 index ef6d17fcf..000000000 --- a/core/.changelog.d/2135.changed +++ /dev/null @@ -1 +0,0 @@ -\[debuglink] Do not wait for screen refresh when _disabling_ layout watching. diff --git a/core/.changelog.d/2144.added b/core/.changelog.d/2144.added deleted file mode 100644 index d89148122..000000000 --- a/core/.changelog.d/2144.added +++ /dev/null @@ -1 +0,0 @@ -Support unverified external inputs. diff --git a/core/.changelog.d/2166.added b/core/.changelog.d/2166.added deleted file mode 100644 index a6d73e923..000000000 --- a/core/.changelog.d/2166.added +++ /dev/null @@ -1 +0,0 @@ -Support Zcash version 5 transaction format diff --git a/core/.changelog.d/2167.fixed b/core/.changelog.d/2167.fixed deleted file mode 100644 index d6b580063..000000000 --- a/core/.changelog.d/2167.fixed +++ /dev/null @@ -1 +0,0 @@ -Support EIP-712 messages where a struct type is only used as an array element. diff --git a/core/.changelog.d/2181.removed b/core/.changelog.d/2181.removed deleted file mode 100644 index 5a50859e1..000000000 --- a/core/.changelog.d/2181.removed +++ /dev/null @@ -1 +0,0 @@ -GAME, NIX and POLIS support diff --git a/core/.changelog.d/2239.added b/core/.changelog.d/2239.added deleted file mode 100644 index 42f72dcd5..000000000 --- a/core/.changelog.d/2239.added +++ /dev/null @@ -1 +0,0 @@ -Add firmware hashing functionality. diff --git a/core/.changelog.d/noissue.security b/core/.changelog.d/noissue.security deleted file mode 100644 index 552e050cd..000000000 --- a/core/.changelog.d/noissue.security +++ /dev/null @@ -1 +0,0 @@ -Fix a coin loss vulnerability related to replacement transactions with multisig inputs and unverified external inputs. diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 1c8ac6c2f..a35333d42 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -4,6 +4,43 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## 2.5.1 [18th May 2022] + +### Added +- Support Bitcoin payment requests. [#1430] +- Show "signature is valid" dialog when VerifyMessage succeeds. [#1880] +- Support ownership proofs for Taproot addresses. [#1944] +- Add extra check for Taproot scripts validity. [#2077] +- Support Electrum signatures in VerifyMessage. [#2100] +- Support Cardano Alonzo-era transactions (Plutus). [#2114] +- Support unverified external inputs. [#2144] +- Support Zcash version 5 transaction format [#2166] +- Add firmware hashing functionality. [#2239] + +### Changed +- Ensure input's script type and path match the scriptPubKey. [#1018] +- Automatically choose best size and encoding for QR codes. [#1751] +- Bitcoin bech32 addresses are encoded in lower-case for QR codes. [#1751] +- Full type-checking for Python code (except Monero app). [#1939] +- \[debuglink] Do not wait for screen refresh when _disabling_ layout watching. [#2135] + +### Removed +- GAME, NIX and POLIS support. [#2181] + +### Fixed +- EIP-1559 transaction correctly show final Hold to Confirm screen. [#2020] +- Fix sighash computation in proofs of ownership. [#2034] +- Fix domain-only EIP-712 hashes (i.e. when `primaryType`=`EIP712Domain`). [#2036] +- Support EIP-712 messages where a struct type is only used as an array element. [#2167] + +### Security +- Fix a coin loss vulnerability related to replacement transactions with multisig inputs and unverified external inputs. + +### Incompatible changes +- Trezor will refuse to sign UTXOs that do not match the provided derivation path (e.g., transactions belonging to a different wallet, or synthetic transaction inputs). [#1018] + + ## 2.4.3 [8th December 2021] ### Added @@ -451,6 +488,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [#948]: https://github.com/trezor/trezor-firmware/pull/948 [#958]: https://github.com/trezor/trezor-firmware/pull/958 [#982]: https://github.com/trezor/trezor-firmware/pull/982 +[#1018]: https://github.com/trezor/trezor-firmware/pull/1018 [#1027]: https://github.com/trezor/trezor-firmware/pull/1027 [#1030]: https://github.com/trezor/trezor-firmware/pull/1030 [#1042]: https://github.com/trezor/trezor-firmware/pull/1042 @@ -494,6 +532,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [#1402]: https://github.com/trezor/trezor-firmware/pull/1402 [#1404]: https://github.com/trezor/trezor-firmware/pull/1404 [#1415]: https://github.com/trezor/trezor-firmware/pull/1415 +[#1430]: https://github.com/trezor/trezor-firmware/pull/1430 [#1431]: https://github.com/trezor/trezor-firmware/pull/1431 [#1456]: https://github.com/trezor/trezor-firmware/pull/1456 [#1467]: https://github.com/trezor/trezor-firmware/pull/1467 @@ -531,6 +570,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [#1708]: https://github.com/trezor/trezor-firmware/pull/1708 [#1710]: https://github.com/trezor/trezor-firmware/pull/1710 [#1744]: https://github.com/trezor/trezor-firmware/pull/1744 +[#1751]: https://github.com/trezor/trezor-firmware/pull/1751 [#1755]: https://github.com/trezor/trezor-firmware/pull/1755 [#1765]: https://github.com/trezor/trezor-firmware/pull/1765 [#1767]: https://github.com/trezor/trezor-firmware/pull/1767 @@ -545,3 +585,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [#1838]: https://github.com/trezor/trezor-firmware/pull/1838 [#1857]: https://github.com/trezor/trezor-firmware/pull/1857 [#1872]: https://github.com/trezor/trezor-firmware/pull/1872 +[#1880]: https://github.com/trezor/trezor-firmware/pull/1880 +[#1939]: https://github.com/trezor/trezor-firmware/pull/1939 +[#1944]: https://github.com/trezor/trezor-firmware/pull/1944 +[#2020]: https://github.com/trezor/trezor-firmware/pull/2020 +[#2034]: https://github.com/trezor/trezor-firmware/pull/2034 +[#2036]: https://github.com/trezor/trezor-firmware/pull/2036 +[#2077]: https://github.com/trezor/trezor-firmware/pull/2077 +[#2100]: https://github.com/trezor/trezor-firmware/pull/2100 +[#2114]: https://github.com/trezor/trezor-firmware/pull/2114 +[#2135]: https://github.com/trezor/trezor-firmware/pull/2135 +[#2144]: https://github.com/trezor/trezor-firmware/pull/2144 +[#2166]: https://github.com/trezor/trezor-firmware/pull/2166 +[#2167]: https://github.com/trezor/trezor-firmware/pull/2167 +[#2181]: https://github.com/trezor/trezor-firmware/pull/2181 +[#2239]: https://github.com/trezor/trezor-firmware/pull/2239