From 5d0063ced7d07a1bbebf76b20ac25c16051afb53 Mon Sep 17 00:00:00 2001 From: Sztergbaum Roman Date: Mon, 25 Sep 2023 14:56:38 +0200 Subject: [PATCH] [BSC]: Thorswap BSC support (#3429) --- src/THORChain/Swap.cpp | 6 ++- src/THORChain/Swap.h | 3 +- src/THORChain/TWSwap.cpp | 1 + src/proto/THORChainSwap.proto | 1 + tests/chains/Cosmos/THORChain/SwapTests.cpp | 56 +++++++++++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/THORChain/Swap.cpp b/src/THORChain/Swap.cpp index 89e53e4a221..9d2f4278524 100644 --- a/src/THORChain/Swap.cpp +++ b/src/THORChain/Swap.cpp @@ -65,6 +65,8 @@ TWCoinType chainCoinType(Chain chain) { return TWCoinTypeLitecoin; case Chain::ATOM: return TWCoinTypeCosmos; + case Chain::BSC: + return TWCoinTypeSmartChain; case Chain::THOR: default: return TWCoinTypeTHORChain; @@ -78,6 +80,7 @@ std::string chainName(Chain chain) { case Chain::ETH: return "ETH"; case Chain::BNB: + case Chain::BSC: return "BNB"; case Chain::BTC: return "BTC"; @@ -127,6 +130,7 @@ SwapBundled SwapBuilder::build(bool shortened) { return buildAtom(fromAmountNum, memo); case Chain::ETH: case Chain::AVAX: + case Chain::BSC: return buildEth(fromAmountNum, memo); } default: @@ -237,7 +241,7 @@ SwapBundled SwapBuilder::buildEth(const uint256_t& amount, const std::string& me Data out; auto input = Ethereum::Proto::SigningInput(); // EIP-1559 - input.set_tx_mode(Ethereum::Proto::Enveloped); + input.set_tx_mode(this->mFromAsset.chain() == Proto::Chain::BSC ? Ethereum::Proto::Legacy : Ethereum::Proto::Enveloped); const auto& toTokenId = mFromAsset.token_id(); // some sanity check / address conversion Data vaultAddressBin = ethAddressStringToData(mVaultAddress); diff --git a/src/THORChain/Swap.h b/src/THORChain/Swap.h index 7f98df6e5d9..e6aa32a3001 100644 --- a/src/THORChain/Swap.h +++ b/src/THORChain/Swap.h @@ -27,7 +27,8 @@ enum Chain { BCH = 5, LTC = 6, ATOM = 7, - AVAX = 8 + AVAX = 8, + BSC = 9, }; using SwapErrorCode = int; diff --git a/src/THORChain/TWSwap.cpp b/src/THORChain/TWSwap.cpp index f1d4b203dc3..22915577761 100644 --- a/src/THORChain/TWSwap.cpp +++ b/src/THORChain/TWSwap.cpp @@ -72,6 +72,7 @@ TWData* _Nonnull TWTHORChainSwapBuildSwap(TWData* _Nonnull input) { } break; case THORChainSwap::Proto::ETH: + case THORChainSwap::Proto::BSC: case THORChainSwap::Proto::AVAX: { Ethereum::Proto::SigningInput ethInput; if (!ethInput.ParseFromArray(txInput.data(), static_cast(txInput.size()))) { diff --git a/src/proto/THORChainSwap.proto b/src/proto/THORChainSwap.proto index 382c2e25f9b..69b6d257e16 100644 --- a/src/proto/THORChainSwap.proto +++ b/src/proto/THORChainSwap.proto @@ -19,6 +19,7 @@ enum Chain { LTC = 6; ATOM = 7; AVAX = 8; + BSC = 9; } // Predefined error codes diff --git a/tests/chains/Cosmos/THORChain/SwapTests.cpp b/tests/chains/Cosmos/THORChain/SwapTests.cpp index 3bcebb89c8c..32db1f54988 100644 --- a/tests/chains/Cosmos/THORChain/SwapTests.cpp +++ b/tests/chains/Cosmos/THORChain/SwapTests.cpp @@ -523,6 +523,62 @@ TEST(THORChainSwap, SwapErc20Rune) { // https://thorchain.net/tx/B5E88D61157E7073995CA8729B75DAB2C1684A7B145DB711327CA4B8FF7DBDE7 } +TEST(THORChainSwap, SwapBscBnb) { + Proto::Asset fromAsset; + fromAsset.set_chain(static_cast(Chain::BSC)); + fromAsset.set_token_id("0x0000000000000000000000000000000000000000"); + Proto::Asset toAsset; + toAsset.set_chain(static_cast(Chain::BNB)); + toAsset.set_symbol("BNB"); + auto&& [out, errorCode, error] = SwapBuilder::builder() + .from(fromAsset) + .to(toAsset) + .fromAddress("0xf8192E9c51c070d199a8F262c12DDD1034274083") + .toAddress("bnb1tjcup6q8nere6r0pdt2ucc4g0xcrhm0jy5xql8") + .vault("0xcBE4334E4a0fC7C5Fa8083223B28a4b9F695A06C") + .router("0xb30eC53F98ff5947EDe720D32aC2da7e52A5f56b") + .fromAmount("10000000000000000") + .toAmountLimit("100000") + .expirationPolicy(1775669796) + .affFeeAddress("t") + .affFeeRate("0") + .build(); + ASSERT_EQ(errorCode, 0); + ASSERT_EQ(error, ""); + EXPECT_EQ(hex(out), "0a01001201002201002a0100422a3078623330654335334639386666353934374544653732304433326143326461376535324135663536625293023290020a072386f26fc1000012840244bc937b000000000000000000000000cbe4334e4a0fc7c5fa8083223b28a4b9f695a06c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000069d69224000000000000000000000000000000000000000000000000000000000000003f3d3a424e422e424e423a626e6231746a6375703671386e65726536723070647432756363346730786372686d306a793578716c383a3130303030303a743a3000"); + + auto tx = Ethereum::Proto::SigningInput(); + ASSERT_TRUE(tx.ParseFromArray(out.data(), (int)out.size())); + + + // check fields + EXPECT_EQ(tx.to_address(), "0xb30eC53F98ff5947EDe720D32aC2da7e52A5f56b"); + ASSERT_TRUE(tx.transaction().has_contract_generic()); + + EXPECT_EQ(hex(TW::data(tx.private_key())), ""); + + // set few fields before signing + auto chainId = store(uint256_t(56)); + tx.set_chain_id(chainId.data(), chainId.size()); + auto nonce = store(uint256_t(0)); + tx.set_nonce(nonce.data(), nonce.size()); + // 0,000000001 + auto gasPrice = store(uint256_t(3000000000)); + tx.set_gas_price(gasPrice.data(), gasPrice.size()); + auto gasLimit = store(uint256_t(50000)); + tx.set_gas_limit(gasLimit.data(), gasLimit.size()); + auto privKey = parse_hex("74c452b55e0da4139172bc3b32bec469cfefbcdce373edda8e33afcfbf9c0a87"); + tx.set_private_key(privKey.data(), privKey.size()); + + // sign and encode resulting input + Ethereum::Proto::SigningOutput output; + ANY_SIGN(tx, TWCoinTypeSmartChain); + EXPECT_EQ(hex(output.encoded()), "f901718084b2d05e0082c35094b30ec53f98ff5947ede720d32ac2da7e52a5f56b872386f26fc10000b9010444bc937b000000000000000000000000cbe4334e4a0fc7c5fa8083223b28a4b9f695a06c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000069d69224000000000000000000000000000000000000000000000000000000000000003f3d3a424e422e424e423a626e6231746a6375703671386e65726536723070647432756363346730786372686d306a793578716c383a3130303030303a743a30008194a05b0032d4150a3fa3b39a047648c02cb44b3256b9c34b7780265643c33d2aa2c6a017fece0465a271b7bddf655f7ac77419fb0433f9acf64b455b9aa17183b6eb98"); + // https://viewblock.io/thorchain/tx/4292A5068BAA5619CF7A35861058915423688DF3CAE8F241453D8FCC6E0BF0A9 + // https://bscscan.com/tx/0x4292a5068baa5619cf7a35861058915423688df3cae8f241453d8fcc6e0bf0a9 + // https://explorer.bnbchain.org/tx/88A1B6F9D64F3B48CE1107979CD325E817446C5D6729EE6FC917589A6FADA79D +} + TEST(THORChainSwap, SwapAvaxBnb) { Proto::Asset fromAsset; fromAsset.set_chain(static_cast(Chain::AVAX));