From 15c27a4bf523b2883b61c8e90b77b91d5faec0e4 Mon Sep 17 00:00:00 2001 From: markrypto Date: Mon, 5 Apr 2021 17:01:09 -0600 Subject: [PATCH 1/3] uniswap add liquidity and approve liquid txs work --- .../firmware/ethereum_contracts/zxappliquid.h | 33 +++ .../firmware/ethereum_contracts/zxliquidtx.h | 33 +++ include/keepkey/firmware/ethereum_tokens.h | 2 + lib/firmware/CMakeLists.txt | 2 + lib/firmware/ethereum_contracts.c | 10 + lib/firmware/ethereum_contracts/zxappliquid.c | 111 ++++++++++ lib/firmware/ethereum_contracts/zxliquidtx.c | 192 ++++++++++++++++++ lib/firmware/ethereum_contracts/zxswap.c | 2 +- lib/firmware/ethereum_tokens.c | 16 ++ 9 files changed, 400 insertions(+), 1 deletion(-) create mode 100644 include/keepkey/firmware/ethereum_contracts/zxappliquid.h create mode 100644 include/keepkey/firmware/ethereum_contracts/zxliquidtx.h create mode 100644 lib/firmware/ethereum_contracts/zxappliquid.c create mode 100644 lib/firmware/ethereum_contracts/zxliquidtx.c diff --git a/include/keepkey/firmware/ethereum_contracts/zxappliquid.h b/include/keepkey/firmware/ethereum_contracts/zxappliquid.h new file mode 100644 index 000000000..d1f14cd75 --- /dev/null +++ b/include/keepkey/firmware/ethereum_contracts/zxappliquid.h @@ -0,0 +1,33 @@ +/* + * This file is part of the KeepKey project. + * + * Copyright (C) 2021 ShapeShift + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef KEEPKEY_FIRMWARE_ETHEREUMCONTRACTS_ZXAPPLIQUIDTX_H +#define KEEPKEY_FIRMWARE_ETHEREUMCONTRACTS_ZXAPPLIQUIDTX_H + +#include +#include + +#define MAX_ALLOWANCE "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x52\xb7\xd2\xdc\xc8\x0c\xd2\xe4\x00\x00\x00" + +typedef struct _EthereumSignTx EthereumSignTx; + +bool zx_isZxApproveLiquid(const EthereumSignTx *msg); +bool zx_confirmApproveLiquidity(uint32_t data_total, const EthereumSignTx *msg); + +#endif diff --git a/include/keepkey/firmware/ethereum_contracts/zxliquidtx.h b/include/keepkey/firmware/ethereum_contracts/zxliquidtx.h new file mode 100644 index 000000000..50a61476d --- /dev/null +++ b/include/keepkey/firmware/ethereum_contracts/zxliquidtx.h @@ -0,0 +1,33 @@ +/* + * This file is part of the KeepKey project. + * + * Copyright (C) 2021 ShapeShift + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef KEEPKEY_FIRMWARE_ETHEREUMCONTRACTS_ZXLIQUIDTX_H +#define KEEPKEY_FIRMWARE_ETHEREUMCONTRACTS_ZXLIQUIDTX_H + +#include +#include + +#define UNISWAP_ROUTER_ADDRESS "\x7a\x25\x0d\x56\x30\xB4\xcF\x53\x97\x39\xdF\x2C\x5d\xAc\xb4\xc6\x59\xF2\x48\x8D" + +typedef struct _EthereumSignTx EthereumSignTx; + +bool zx_isZxLiquidTx(const EthereumSignTx *msg); +bool zx_confirmZxLiquidTx(uint32_t data_total, const EthereumSignTx *msg); + +#endif diff --git a/include/keepkey/firmware/ethereum_tokens.h b/include/keepkey/firmware/ethereum_tokens.h index a222eae1c..ad7683ba8 100644 --- a/include/keepkey/firmware/ethereum_tokens.h +++ b/include/keepkey/firmware/ethereum_tokens.h @@ -49,6 +49,8 @@ extern const TokenType tokens[]; extern const TokenType *UnknownToken; +const TokenType *tokenIter(int32_t *ctr); + const TokenType *tokenByChainAddress(uint8_t chain_id, const uint8_t *address); /// Tokens don't have unique tickers, so this might not return the one you're diff --git a/lib/firmware/CMakeLists.txt b/lib/firmware/CMakeLists.txt index 7dda2e251..1f1e249fd 100644 --- a/lib/firmware/CMakeLists.txt +++ b/lib/firmware/CMakeLists.txt @@ -11,6 +11,8 @@ set(sources ethereum.c ethereum_contracts.c ethereum_contracts/makerdao.c + ethereum_contracts/zxappliquid.c + ethereum_contracts/zxliquidtx.c ethereum_contracts/zxswap.c ethereum_tokens.c exchange.c diff --git a/lib/firmware/ethereum_contracts.c b/lib/firmware/ethereum_contracts.c index ce0e68f59..d7fbefb5f 100644 --- a/lib/firmware/ethereum_contracts.c +++ b/lib/firmware/ethereum_contracts.c @@ -19,6 +19,8 @@ #include "keepkey/firmware/ethereum_contracts.h" +#include "keepkey/firmware/ethereum_contracts/zxappliquid.h" +#include "keepkey/firmware/ethereum_contracts/zxliquidtx.h" #include "keepkey/firmware/ethereum_contracts/zxswap.h" #include "keepkey/firmware/ethereum_contracts/makerdao.h" @@ -28,6 +30,8 @@ bool ethereum_contractHandled(uint32_t data_total, const EthereumSignTx *msg, if (zx_isZxSwap(msg)) return true; + if (zx_isZxLiquidTx(msg)) return true; + if (zx_isZxApproveLiquid(msg)) return true; if (makerdao_isMakerDAO(data_total, msg)) return true; @@ -40,6 +44,12 @@ bool ethereum_contractConfirmed(uint32_t data_total, const EthereumSignTx *msg, if (zx_isZxSwap(msg)) return zx_confirmZxSwap(data_total, msg); + + if (zx_isZxLiquidTx(msg)) + return zx_confirmZxLiquidTx(data_total, msg); + + if (zx_isZxApproveLiquid(msg)) + return zx_confirmApproveLiquidity(data_total, msg); if (makerdao_isMakerDAO(data_total, msg)) return makerdao_confirmMakerDAO(data_total, msg); diff --git a/lib/firmware/ethereum_contracts/zxappliquid.c b/lib/firmware/ethereum_contracts/zxappliquid.c new file mode 100644 index 000000000..c4eef14b0 --- /dev/null +++ b/lib/firmware/ethereum_contracts/zxappliquid.c @@ -0,0 +1,111 @@ +/* + * This file is part of the KeepKey project. + * + * Copyright (C) 2021 ShapeShift + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include "keepkey/firmware/ethereum_contracts/zxappliquid.h" +#include "keepkey/firmware/ethereum_contracts/zxliquidtx.h" + +#include "keepkey/board/confirm_sm.h" +#include "keepkey/board/util.h" +#include "keepkey/firmware/app_confirm.h" +#include "keepkey/firmware/coins.h" +#include "keepkey/firmware/ethereum.h" +#include "keepkey/firmware/ethereum_tokens.h" +#include "keepkey/firmware/fsm.h" +#include "keepkey/firmware/storage.h" +#include "trezor/crypto/address.h" +#include "trezor/crypto/bip32.h" +#include "trezor/crypto/curves.h" +#include "trezor/crypto/memzero.h" +#include "trezor/crypto/sha3.h" + +bool zx_confirmApproveLiquidity(uint32_t data_total, const EthereumSignTx *msg) { + (void)data_total; + const char *to, *tikstr, *poolstr, *allowance, *amt; + unsigned char data[40]; + uint8_t digest[SHA3_256_DIGEST_LENGTH] = {0}; + uint8_t tokdigest[SHA3_256_DIGEST_LENGTH] = {0}; + char digestStr[2*SHA3_256_DIGEST_LENGTH+1], amtStr[2*32+1] = {0}; + int32_t ctr, tokctr; + uint32_t wethord, ttokenord; + const TokenType *WETH, *ttoken; + + if (!tokenByTicker(msg->chain_id, "WETH", &WETH)) return false; + wethord = read_be((const uint8_t *)WETH->address); + to = (const char *)msg->to.bytes; + tokctr = 0; + while (tokctr != -1) { + ttoken = tokenIter(&tokctr); + + //https://uniswap.org/docs/v2/smart-contract-integration/getting-pair-addresses/ + ttokenord = read_be((const uint8_t *)ttoken->address); + if (ttokenord < wethord) { + memcpy(data, ttoken->address, 20); + memcpy(&data[20], WETH->address, 20); + } else { + memcpy(data, WETH->address, 20); + memcpy(&data[20], ttoken->address, 20); + } + keccak_256(data, sizeof(data), tokdigest); + SHA3_CTX ctx = {0}; + keccak_256_Init(&ctx); + keccak_Update(&ctx, (unsigned char *)"\xff", 1); + keccak_Update(&ctx, (unsigned char *)"\x5C\x69\xbE\xe7\x01\xef\x81\x4a\x2B\x6a\x3E\xDD\x4B\x16\x52\xCB\x9c\xc5\xaA\x6f", 20); + keccak_Update(&ctx, tokdigest, sizeof(tokdigest)); + keccak_Update(&ctx, (unsigned char *)"\x96\xe8\xac\x42\x77\x19\x8f\xf8\xb6\xf7\x85\x47\x8a\xa9\xa3\x9f\x40\x3c\xb7\x68\xdd\x02\xcb\xee\x32\x6c\x3e\x7d\xa3\x48\x84\x5f", 32); + keccak_Final(&ctx, digest); + if (memcmp(to, &digest[12], 20) == 0) break; + } + + if (tokctr != -1) { + for (ctr=0; ctrticker; + poolstr = &digestStr[12*2]; + } else { + for (ctr=0; ctr<20; ctr++) { + snprintf(&digestStr[ctr*2], 3, "%02x", to[ctr]); + } + tikstr = ""; + poolstr = digestStr; + } + + allowance = (char *)(msg->data_initial_chunk.bytes + 4 +32); + if (memcmp(allowance, (uint8_t *)&MAX_ALLOWANCE, 32) == 0) { + amt = "full balance"; + } else { + for (ctr=0; ctr<32; ctr++) { + snprintf(&amtStr[ctr*2], 3, "%02x", allowance[ctr]); + } + amt = amtStr; + } + + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap approve liquidity", + "Amount: %s", amt); + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap approve liquidity", + "approve for pool %s %s", tikstr, poolstr); + return true; +} + +bool zx_isZxApproveLiquid(const EthereumSignTx *msg) { + if (memcmp(msg->data_initial_chunk.bytes, "\x09\x5e\xa7\xb3", 4) == 0) + if (memcmp((uint8_t *)(msg->data_initial_chunk.bytes + 4 + 32 - 20), UNISWAP_ROUTER_ADDRESS, 20) == 0) + return true; + return false; +} diff --git a/lib/firmware/ethereum_contracts/zxliquidtx.c b/lib/firmware/ethereum_contracts/zxliquidtx.c new file mode 100644 index 000000000..cafba3f6d --- /dev/null +++ b/lib/firmware/ethereum_contracts/zxliquidtx.c @@ -0,0 +1,192 @@ +/* + * This file is part of the KeepKey project. + * + * Copyright (C) 2021 ShapeShift + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include "keepkey/firmware/ethereum_contracts/zxliquidtx.h" + +#include "keepkey/board/confirm_sm.h" +#include "keepkey/board/util.h" +#include "keepkey/firmware/app_confirm.h" +#include "keepkey/firmware/coins.h" +#include "keepkey/firmware/ethereum.h" +#include "keepkey/firmware/ethereum_tokens.h" +#include "keepkey/firmware/fsm.h" +#include "keepkey/firmware/storage.h" +#include "trezor/crypto/address.h" +#include "trezor/crypto/bip32.h" +#include "trezor/crypto/curves.h" +#include "trezor/crypto/memzero.h" +#include "trezor/crypto/sha3.h" + +static HDNode *zx_getDerivedNode(const char *curve, const uint32_t *address_n, + size_t address_n_count, + uint32_t *fingerprint) { + static HDNode CONFIDENTIAL node; + if (fingerprint) { + *fingerprint = 0; + } + + if (!get_curve_by_name(curve)) { + return 0; + } + + if (!storage_getRootNode(curve, true, &node)) { + return 0; + } + + if (!address_n || address_n_count == 0) { + return &node; + } + + if (hdnode_private_ckd_cached(&node, address_n, address_n_count, + fingerprint) == 0) { + return 0; + } + + return &node; +} + + +static bool isAddLiquidityEthCall(const EthereumSignTx *msg) { + if (memcmp(msg->data_initial_chunk.bytes, "\xf3\x05\xd7\x19", 4) == 0) + return true; + + return false; +} + +static bool isRemoveLiquidityEthCall(const EthereumSignTx *msg) { + if (memcmp(msg->data_initial_chunk.bytes, "\x02\x75\x1c\xec", 4) == 0) + return true; + + return false; +} + +static bool confirmFromAccountMatch(const EthereumSignTx *msg) { + // Determine withdrawal address + char addressStr[43] = {'0', 'x'}; + char *fromSrc; + uint8_t *fromAddress; + uint8_t addressBytes[20]; + + HDNode *node = zx_getDerivedNode(SECP256K1_NAME, msg->address_n, + msg->address_n_count, NULL); + if (!node) return false; + + if (!hdnode_get_ethereum_pubkeyhash(node, addressBytes)) { + memzero(node, sizeof(*node)); + } + + bool rskip60 = false; + uint32_t chain_id = 0; + + if (msg->address_n_count == 5) { + uint32_t slip44 = msg->address_n[1] & 0x7fffffff; + // constants from trezor-common/defs/ethereum/networks.json + switch (slip44) { + case 137: + rskip60 = true; + chain_id = 30; + break; + case 37310: + rskip60 = true; + chain_id = 31; + break; + } + } + + ethereum_address_checksum(addressBytes, addressStr + 2, rskip60, + chain_id); + + fromAddress = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 5*32 - 20); + + if (memcmp(fromAddress, addressBytes, 20) == 0) { + fromSrc = "self"; + } else { + fromSrc = "NOT this wallet"; + } + + if (!confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "Uniswap Add Liquidity", + "Confirming ETH sending from %s: %s", fromSrc, addressStr)) { + return false; + } + return true; +} + +bool zx_isZxLiquidTx(const EthereumSignTx *msg) { + if (memcmp(msg->to.bytes, UNISWAP_ROUTER_ADDRESS, 20) == 0) { // correct contract address? + + if (isAddLiquidityEthCall(msg)) return true; + + if (isRemoveLiquidityEthCall(msg)) return true; + } + return false; +} + +bool zx_confirmZxLiquidTx(uint32_t data_total, const EthereumSignTx *msg) { + (void)data_total; + const TokenType *token; + char constr1[40], constr2[40]; + uint8_t *tokenAddress, *deadlineBytes; + bignum256 tokenAmount, tokenMinAmount, ethMinAmount; + uint64_t deadline; + + if (isAddLiquidityEthCall(msg)) { // add liquidity confirm + tokenAddress = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 32 - 20); + token = tokenByChainAddress(msg->chain_id, tokenAddress); + bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 32, 32, &tokenAmount); + bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 2*32, 32, &tokenMinAmount); + bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 3*32, 32, ðMinAmount); + + // bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 6*32 - 8, 8, &deadline); + deadlineBytes = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 6*32 - 8); + deadline = ((uint64_t)deadlineBytes[0] << 8*7) | + ((uint64_t)deadlineBytes[1] << 8*6) | + ((uint64_t)deadlineBytes[2] << 8*5) | + ((uint64_t)deadlineBytes[3] << 8*4) | + ((uint64_t)deadlineBytes[4] << 8*3) | + ((uint64_t)deadlineBytes[5] << 8*2) | + ((uint64_t)deadlineBytes[6] << 8*1) | + ((uint64_t)deadlineBytes[7]); + + char tokbuf[32]; + ethereumFormatAmount(&tokenAmount, token, msg->chain_id, tokbuf, sizeof(tokbuf)); + snprintf(constr1, 32, "%s", tokbuf); + ethereumFormatAmount(&tokenMinAmount, token, msg->chain_id, tokbuf, sizeof(tokbuf)); + snprintf(constr2, 32, "%s", tokbuf); + + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap add liquidity", + "Add %s\nMinimum %s", constr1, constr2); + + if (!confirmFromAccountMatch(msg)) { + return false; + } + + ethereumFormatAmount(ðMinAmount, NULL, msg->chain_id, tokbuf, sizeof(tokbuf)); + snprintf(constr1, 32, "%s", tokbuf); + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap add liquidity", + "Add Minimum %s", constr1); + + snprintf(constr1, 32, "%lld", deadline); + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap add liquidity", + "Deadline (unix ref) %s", constr1); + + return true; + } + + return true; +} diff --git a/lib/firmware/ethereum_contracts/zxswap.c b/lib/firmware/ethereum_contracts/zxswap.c index 177e95856..36b9d4e93 100644 --- a/lib/firmware/ethereum_contracts/zxswap.c +++ b/lib/firmware/ethereum_contracts/zxswap.c @@ -1,7 +1,7 @@ /* * This file is part of the KeepKey project. * - * Copyright (C) 2019 ShapeShift + * Copyright (C) 2021 ShapeShift * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/lib/firmware/ethereum_tokens.c b/lib/firmware/ethereum_tokens.c index f19926345..204aed081 100644 --- a/lib/firmware/ethereum_tokens.c +++ b/lib/firmware/ethereum_tokens.c @@ -26,6 +26,22 @@ static const TokenType Ethtest = { " ETH", 1, 18}; const TokenType *EthTestToken = (const TokenType *)&Ethtest; +const TokenType *tokenIter(int32_t *ctr) { + // return the next tok in the list. + // input: *ctr = position of desired token (0 to TOKENS_COUNT) + // output: returns token at list count *ctr at input for 0 <= *ctr < TOKEN_COUNT + // *ctr = position of next token in list, OR -1 for end of list + + if (*ctr < 0 || *ctr >= TOKENS_COUNT) { + *ctr = -1; + return UnknownToken; + } + + *ctr+=1; + return &(tokens[*ctr - 1]); + +} + const TokenType *tokenByChainAddress(uint8_t chain_id, const uint8_t *address) { if (!address) return 0; for (int i = 0; i < TOKENS_COUNT; i++) { From 3022c5c9a10bc40d74b9a1fcc812f081029b980a Mon Sep 17 00:00:00 2001 From: markrypto Date: Wed, 7 Apr 2021 18:45:27 -0600 Subject: [PATCH 2/3] bump version --- CMakeLists.txt | 2 +- .../firmware/ethereum_contracts/zxappliquid.h | 2 +- lib/firmware/ethereum_contracts/zxappliquid.c | 5 +- lib/firmware/ethereum_contracts/zxliquidtx.c | 117 ++++++++---------- 4 files changed, 54 insertions(+), 72 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aaca04223..38c97d035 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.7.2) project(KeepKeyFirmware - VERSION 7.0.3 + VERSION 7.1.0 LANGUAGES C CXX ASM) diff --git a/include/keepkey/firmware/ethereum_contracts/zxappliquid.h b/include/keepkey/firmware/ethereum_contracts/zxappliquid.h index d1f14cd75..0290b9e9f 100644 --- a/include/keepkey/firmware/ethereum_contracts/zxappliquid.h +++ b/include/keepkey/firmware/ethereum_contracts/zxappliquid.h @@ -23,7 +23,7 @@ #include #include -#define MAX_ALLOWANCE "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x52\xb7\xd2\xdc\xc8\x0c\xd2\xe4\x00\x00\x00" +#define MAX_ALLOWANCE "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" typedef struct _EthereumSignTx EthereumSignTx; diff --git a/lib/firmware/ethereum_contracts/zxappliquid.c b/lib/firmware/ethereum_contracts/zxappliquid.c index c4eef14b0..7fa3db963 100644 --- a/lib/firmware/ethereum_contracts/zxappliquid.c +++ b/lib/firmware/ethereum_contracts/zxappliquid.c @@ -96,9 +96,10 @@ bool zx_confirmApproveLiquidity(uint32_t data_total, const EthereumSignTx *msg) amt = amtStr; } - confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap approve liquidity", + char *appStr = "uniswap approve liquidity"; + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, appStr, "Amount: %s", amt); - confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap approve liquidity", + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, appStr, "approve for pool %s %s", tikstr, poolstr); return true; } diff --git a/lib/firmware/ethereum_contracts/zxliquidtx.c b/lib/firmware/ethereum_contracts/zxliquidtx.c index cafba3f6d..2789b014a 100644 --- a/lib/firmware/ethereum_contracts/zxliquidtx.c +++ b/lib/firmware/ethereum_contracts/zxliquidtx.c @@ -61,7 +61,6 @@ static HDNode *zx_getDerivedNode(const char *curve, const uint32_t *address_n, return &node; } - static bool isAddLiquidityEthCall(const EthereumSignTx *msg) { if (memcmp(msg->data_initial_chunk.bytes, "\xf3\x05\xd7\x19", 4) == 0) return true; @@ -76,9 +75,9 @@ static bool isRemoveLiquidityEthCall(const EthereumSignTx *msg) { return false; } -static bool confirmFromAccountMatch(const EthereumSignTx *msg) { +static bool confirmFromAccountMatch(const EthereumSignTx *msg, char *addremStr) { // Determine withdrawal address - char addressStr[43] = {'0', 'x'}; + char addressStr[43] = {'0', 'x', '\0'}; char *fromSrc; uint8_t *fromAddress; uint8_t addressBytes[20]; @@ -91,27 +90,6 @@ static bool confirmFromAccountMatch(const EthereumSignTx *msg) { memzero(node, sizeof(*node)); } - bool rskip60 = false; - uint32_t chain_id = 0; - - if (msg->address_n_count == 5) { - uint32_t slip44 = msg->address_n[1] & 0x7fffffff; - // constants from trezor-common/defs/ethereum/networks.json - switch (slip44) { - case 137: - rskip60 = true; - chain_id = 30; - break; - case 37310: - rskip60 = true; - chain_id = 31; - break; - } - } - - ethereum_address_checksum(addressBytes, addressStr + 2, rskip60, - chain_id); - fromAddress = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 5*32 - 20); if (memcmp(fromAddress, addressBytes, 20) == 0) { @@ -120,8 +98,12 @@ static bool confirmFromAccountMatch(const EthereumSignTx *msg) { fromSrc = "NOT this wallet"; } - if (!confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "Uniswap Add Liquidity", - "Confirming ETH sending from %s: %s", fromSrc, addressStr)) { + for (uint32_t ctr=0; ctr<20; ctr++) { + snprintf(&addressStr[2+ctr*2], 3, "%02x", fromAddress[ctr]); + } + + if (!confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, addremStr, + "Confirming ETH address is %s: %s", fromSrc, addressStr)) { return false; } return true; @@ -140,53 +122,52 @@ bool zx_isZxLiquidTx(const EthereumSignTx *msg) { bool zx_confirmZxLiquidTx(uint32_t data_total, const EthereumSignTx *msg) { (void)data_total; const TokenType *token; - char constr1[40], constr2[40]; + char constr1[40], constr2[40], *arStr = ""; uint8_t *tokenAddress, *deadlineBytes; bignum256 tokenAmount, tokenMinAmount, ethMinAmount; uint64_t deadline; - if (isAddLiquidityEthCall(msg)) { // add liquidity confirm - tokenAddress = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 32 - 20); - token = tokenByChainAddress(msg->chain_id, tokenAddress); - bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 32, 32, &tokenAmount); - bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 2*32, 32, &tokenMinAmount); - bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 3*32, 32, ðMinAmount); - - // bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 6*32 - 8, 8, &deadline); - deadlineBytes = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 6*32 - 8); - deadline = ((uint64_t)deadlineBytes[0] << 8*7) | - ((uint64_t)deadlineBytes[1] << 8*6) | - ((uint64_t)deadlineBytes[2] << 8*5) | - ((uint64_t)deadlineBytes[3] << 8*4) | - ((uint64_t)deadlineBytes[4] << 8*3) | - ((uint64_t)deadlineBytes[5] << 8*2) | - ((uint64_t)deadlineBytes[6] << 8*1) | - ((uint64_t)deadlineBytes[7]); - - char tokbuf[32]; - ethereumFormatAmount(&tokenAmount, token, msg->chain_id, tokbuf, sizeof(tokbuf)); - snprintf(constr1, 32, "%s", tokbuf); - ethereumFormatAmount(&tokenMinAmount, token, msg->chain_id, tokbuf, sizeof(tokbuf)); - snprintf(constr2, 32, "%s", tokbuf); - - confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap add liquidity", - "Add %s\nMinimum %s", constr1, constr2); - - if (!confirmFromAccountMatch(msg)) { - return false; - } - - ethereumFormatAmount(ðMinAmount, NULL, msg->chain_id, tokbuf, sizeof(tokbuf)); - snprintf(constr1, 32, "%s", tokbuf); - confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap add liquidity", - "Add Minimum %s", constr1); - - snprintf(constr1, 32, "%lld", deadline); - confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, "uniswap add liquidity", - "Deadline (unix ref) %s", constr1); + if (isAddLiquidityEthCall(msg)) { + arStr = "uniswap add liquidity"; + } else if (isRemoveLiquidityEthCall(msg)) { + arStr = "uniswap remove liquidity"; + } else { + return false; + } - return true; + tokenAddress = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 32 - 20); + token = tokenByChainAddress(msg->chain_id, tokenAddress); + bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 32, 32, &tokenAmount); + bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 2*32, 32, &tokenMinAmount); + bn_from_bytes(msg->data_initial_chunk.bytes + 4 + 3*32, 32, ðMinAmount); + deadlineBytes = (uint8_t *)(msg->data_initial_chunk.bytes + 4 + 6*32 - 8); + deadline = ((uint64_t)deadlineBytes[0] << 8*7) | + ((uint64_t)deadlineBytes[1] << 8*6) | + ((uint64_t)deadlineBytes[2] << 8*5) | + ((uint64_t)deadlineBytes[3] << 8*4) | + ((uint64_t)deadlineBytes[4] << 8*3) | + ((uint64_t)deadlineBytes[5] << 8*2) | + ((uint64_t)deadlineBytes[6] << 8*1) | + ((uint64_t)deadlineBytes[7]); + + char tokbuf[32]; + ethereumFormatAmount(&tokenAmount, token, msg->chain_id, tokbuf, sizeof(tokbuf)); + snprintf(constr1, 32, "%s", tokbuf); + ethereumFormatAmount(&tokenMinAmount, token, msg->chain_id, tokbuf, sizeof(tokbuf)); + snprintf(constr2, 32, "%s", tokbuf); + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, arStr, + "%s\nMinimum %s", constr1, constr2); + if (!confirmFromAccountMatch(msg, arStr)) { + return false; } - return true; + ethereumFormatAmount(ðMinAmount, NULL, msg->chain_id, tokbuf, sizeof(tokbuf)); + snprintf(constr1, 32, "%s", tokbuf); + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, arStr, + "Minimum %s", constr1); + snprintf(constr1, 32, "%lld", deadline); + confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, arStr, + "Deadline (unix ref) %s", constr1); + + return true; } From 974f2bee29a2542a326da6d9c2b05e8f7db74e4a Mon Sep 17 00:00:00 2001 From: markrypto Date: Thu, 8 Apr 2021 17:45:16 -0600 Subject: [PATCH 3/3] fix some bugs --- lib/firmware/ethereum_contracts/zxliquidtx.c | 5 ++++- lib/firmware/recovery_cipher.c | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/firmware/ethereum_contracts/zxliquidtx.c b/lib/firmware/ethereum_contracts/zxliquidtx.c index 2789b014a..2d65ed98f 100644 --- a/lib/firmware/ethereum_contracts/zxliquidtx.c +++ b/lib/firmware/ethereum_contracts/zxliquidtx.c @@ -33,6 +33,8 @@ #include "trezor/crypto/memzero.h" #include "trezor/crypto/sha3.h" +#include + static HDNode *zx_getDerivedNode(const char *curve, const uint32_t *address_n, size_t address_n_count, uint32_t *fingerprint) { @@ -165,9 +167,10 @@ bool zx_confirmZxLiquidTx(uint32_t data_total, const EthereumSignTx *msg) { snprintf(constr1, 32, "%s", tokbuf); confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, arStr, "Minimum %s", constr1); + snprintf(constr1, 32, "%lld", deadline); confirm(ButtonRequestType_ButtonRequest_ConfirmOutput, arStr, - "Deadline (unix ref) %s", constr1); + "Deadline %s", ctime((const time_t *)&deadline)); return true; } diff --git a/lib/firmware/recovery_cipher.c b/lib/firmware/recovery_cipher.c index 07f5ca969..9677db5c6 100644 --- a/lib/firmware/recovery_cipher.c +++ b/lib/firmware/recovery_cipher.c @@ -588,8 +588,7 @@ void recovery_cipher_finalize(void) { } /* Truncate additional space at the end */ - new_mnemonic[MAX(1u, strnlen(new_mnemonic, sizeof(new_mnemonic)) - 1u)] = '\0'; - + new_mnemonic[MAX(1u, strnlen(new_mnemonic, sizeof(new_mnemonic))) - 1u] = '\0'; if (!dry_run && (!enforce_wordlist || mnemonic_check(new_mnemonic))) { storage_setMnemonic(new_mnemonic); memzero(new_mnemonic, sizeof(new_mnemonic));