diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt
index bef1b60cea7..94b2f723f45 100644
--- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt
+++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt
@@ -45,7 +45,7 @@ class CoinAddressDerivationTests {
ETHEREUM, SMARTCHAIN, POLYGON, OPTIMISM, ZKSYNC, ARBITRUM, ECOCHAIN, AVALANCHECCHAIN, XDAI,
FANTOM, CELO, CRONOSCHAIN, SMARTBITCOINCASH, KUCOINCOMMUNITYCHAIN, BOBA, METIS,
AURORA, EVMOS, MOONRIVER, MOONBEAM, KAVAEVM, KLAYTN, METER, OKXCHAIN, POLYGONZKEVM, SCROLL,
- CONFLUXESPACE, ACALAEVM, OPBNBTESTNET, NEON -> assertEquals("0x8f348F300873Fd5DA36950B2aC75a26584584feE", address)
+ CONFLUXESPACE, ACALAEVM, OPBNBTESTNET, NEON, BASE -> assertEquals("0x8f348F300873Fd5DA36950B2aC75a26584584feE", address)
RONIN -> assertEquals("ronin:8f348F300873Fd5DA36950B2aC75a26584584feE", address)
ETHEREUMCLASSIC -> assertEquals("0x078bA3228F3E6C08bEEac9A005de0b7e7089aD1c", address)
GOCHAIN -> assertEquals("0x5940ce4A14210d4Ccd0ac206CE92F21828016aC2", address)
diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/aptos/TestAptosSigner.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/aptos/TestAptosSigner.kt
index 2b9d9b416c1..f16a3be8300 100644
--- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/aptos/TestAptosSigner.kt
+++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/aptos/TestAptosSigner.kt
@@ -103,4 +103,47 @@ class TestAptosSigner {
"07968dab936c1bad187c60ce4082f307d030d780e91e694ae03aef16aba73f3063000000000000000200000000000000000000000000000000000000000000000000000000000000010d6170746f735f6163636f756e74087472616e7366657200022007968dab936c1bad187c60ce4082f307d030d780e91e694ae03aef16aba73f3008e803000000000000fe4d3200000000006400000000000000c2276ada00000000210020ea526ba1710343d953461ff68641f1b7df5f23b9042ffa2d2a798d3adb3f3d6c405707246db31e2335edc4316a7a656a11691d1d1647f6e864d1ab12f43428aaaf806cf02120d0b608cdd89c5c904af7b137432aacdd60cc53f9fad7bd33578e01"
)
}
+
+ @Test
+ fun AptosTransferTokensCoins() {
+ // Successfully broadcasted https://explorer.aptoslabs.com/txn/0x197d40ea12e2bfc65a0a913b9f4ca3b0b0208fe0c1514d3d55cef3d5bcf25211?network=mainnet
+ val key =
+ "e7f56c77189e03699a75d8ec5c090e41f3d9d4783bc49c33df8a93d915e10de8".toHexBytesInByteString()
+
+ val function = Aptos.StructTag.newBuilder()
+ .setAccountAddress("0xe9c192ff55cffab3963c695cff6dbf9dad6aff2bb5ac19a6415cad26a81860d9")
+ .setModule("mee_coin")
+ .setName("MeeCoin")
+ .build()
+
+ val transfer = Aptos.TokenTransferCoinsMessage.newBuilder()
+ .setAmount(10000)
+ .setTo("0xb7c7d12080209e9dc14498c80200706e760363fb31782247e82cf57d1d6e5d6c")
+ .setFunction(function)
+ .build()
+ val signingInput = Aptos.SigningInput.newBuilder()
+ .setChainId(1)
+ .setSender("0x1869b853768f0ba935d67f837a66b172dd39a60ca2315f8d4e0e669bbd35cf25")
+ .setSequenceNumber(2)
+ .setGasUnitPrice(100)
+ .setMaxGasAmount(2000)
+ .setExpirationTimestampSecs(3664390082)
+ .setTokenTransferCoins(transfer)
+ .setPrivateKey(key)
+ .build()
+
+ val result = AnySigner.sign(signingInput, CoinType.APTOS, Aptos.SigningOutput.parser())
+ assertEquals(
+ Numeric.cleanHexPrefix(Numeric.toHexString(result.rawTxn.toByteArray())),
+ "1869b853768f0ba935d67f837a66b172dd39a60ca2315f8d4e0e669bbd35cf2502000000000000000200000000000000000000000000000000000000000000000000000000000000010d6170746f735f6163636f756e740e7472616e736665725f636f696e730107e9c192ff55cffab3963c695cff6dbf9dad6aff2bb5ac19a6415cad26a81860d9086d65655f636f696e074d6565436f696e000220b7c7d12080209e9dc14498c80200706e760363fb31782247e82cf57d1d6e5d6c081027000000000000d0070000000000006400000000000000c2276ada0000000001"
+ )
+ assertEquals(
+ Numeric.cleanHexPrefix(Numeric.toHexString(result.authenticator.signature.toByteArray())),
+ "30ebd7e95cb464677f411868e2cbfcb22bc01cc63cded36c459dff45e6d2f1354ae4e090e7dfbb509851c0368b343e0e5ecaf6b08e7c1b94c186530b0f7dee0d"
+ )
+ assertEquals(
+ Numeric.cleanHexPrefix(Numeric.toHexString(result.encoded.toByteArray())),
+ "1869b853768f0ba935d67f837a66b172dd39a60ca2315f8d4e0e669bbd35cf2502000000000000000200000000000000000000000000000000000000000000000000000000000000010d6170746f735f6163636f756e740e7472616e736665725f636f696e730107e9c192ff55cffab3963c695cff6dbf9dad6aff2bb5ac19a6415cad26a81860d9086d65655f636f696e074d6565436f696e000220b7c7d12080209e9dc14498c80200706e760363fb31782247e82cf57d1d6e5d6c081027000000000000d0070000000000006400000000000000c2276ada0000000001002062e7a6a486553b56a53e89dfae3f780693e537e5b0a7ed33290780e581ca83694030ebd7e95cb464677f411868e2cbfcb22bc01cc63cded36c459dff45e6d2f1354ae4e090e7dfbb509851c0368b343e0e5ecaf6b08e7c1b94c186530b0f7dee0d"
+ )
+ }
}
diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/bitcoin/TestBitcoinFee.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/bitcoin/TestBitcoinFee.kt
index 5e8a4291060..15d4ee2d593 100644
--- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/bitcoin/TestBitcoinFee.kt
+++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/bitcoin/TestBitcoinFee.kt
@@ -14,20 +14,20 @@ class TestBitcoinFee {
@Test
fun P2pkhCalculateFee() {
- val satVb: Long = 10
+ val satVb = "10"
val tx = Numeric.hexStringToByteArray("02000000017be4e642bb278018ab12277de9427773ad1c5f5b1d164a157e0d99aa48dc1c1e000000006a473044022078eda020d4b86fcb3af78ef919912e6d79b81164dbbb0b0b96da6ac58a2de4b102201a5fd8d48734d5a02371c4b5ee551a69dca3842edbf577d863cf8ae9fdbbd4590121036666dd712e05a487916384bfcd5973eb53e8038eccbbf97f7eed775b87389536ffffffff01c0aff629010000001976a9145eaaa4f458f9158f86afcba08dd7448d27045e3d88ac00000000")
- var fee = BitcoinFee.calculateFee(tx, satVb)
+ var fee = BitcoinFee.calculateFee(tx, satVb).toLong()
- assertEquals(fee, 191 * satVb)
+ assertEquals(fee, 191 * satVb.toLong())
}
@Test
fun P2wpkhCalculateFee() {
- val satVb: Long = 12
+ val satVb = "12"
val tx = Numeric.hexStringToByteArray("020000000111b9f62923af73e297abb69f749e7a1aa2735fbdfd32ac5f6aa89e5c96841c18000000006b483045022100df9ed0b662b759e68b89a42e7144cddf787782a7129d4df05642dd825930e6e6022051a08f577f11cc7390684bbad2951a6374072253ffcf2468d14035ed0d8cd6490121028d7dce6d72fb8f7af9566616c6436349c67ad379f2404dd66fe7085fe0fba28fffffffff01c0aff629010000001600140d0e1cec6c2babe8badde5e9b3dea667da90036d00000000")
- var fee = BitcoinFee.calculateFee(tx, satVb)
+ var fee = BitcoinFee.calculateFee(tx, satVb).toLong()
- assertEquals(fee, 189 * satVb)
+ assertEquals(fee, 189 * satVb.toLong())
}
@Test
@@ -38,10 +38,10 @@ class TestBitcoinFee {
// Size 235 Bytes
// Weight 610
fun Brc20TransferCommitCalculateFee() {
- val satVb: Long = 19
+ val satVb = "19"
val tx = Numeric.hexStringToByteArray("02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000")
- var fee = BitcoinFee.calculateFee(tx, satVb)
+ var fee = BitcoinFee.calculateFee(tx, satVb).toLong()
- assertEquals(fee, 153 * satVb) // 153 = ceil(610/4)
+ assertEquals(fee, 153 * satVb.toLong()) // 153 = ceil(610/4)
}
}
diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt
index cb9d745f96e..235cd442b73 100644
--- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt
+++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt
@@ -34,10 +34,21 @@ class TestBarz {
val publicKeyData = Numeric.hexStringToByteArray("04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")
val publicKey = PublicKey(publicKeyData, PublicKeyType.NIST256P1EXTENDED)
val verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
- val result = WCBarz.getInitCode(factoryAddress, publicKey, verificationFacet)
+ val result = WCBarz.getInitCode(factoryAddress, publicKey, verificationFacet, 0)
assertEquals(Numeric.toHexString(result), "0x3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000")
}
+ @Test
+ fun testInitCodeNonZeroSalt() {
+ val factoryAddress = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800"
+ val publicKeyData = Numeric.hexStringToByteArray("04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")
+ val publicKey = PublicKey(publicKeyData, PublicKeyType.NIST256P1EXTENDED)
+ val verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
+ val salt = 1
+ val result = WCBarz.getInitCode(factoryAddress, publicKey, verificationFacet, salt)
+ assertEquals(Numeric.toHexString(result), "0x3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000")
+ }
+
@Test
fun testCounterfactualAddress() {
val input = Barz.ContractAddressInput.newBuilder()
@@ -55,6 +66,24 @@ class TestBarz {
assertEquals(result, "0x77F62bb3E43190253D4E198199356CD2b25063cA")
}
+ @Test
+ fun testCounterfactualAddressNonZeroSalt() {
+ val input = Barz.ContractAddressInput.newBuilder()
+ input.apply {
+ factory = "0x96C489979E39F877BDb8637b75A25C1a5B2DE14C"
+ accountFacet = "0xF6F5e5fC74905e65e3FF53c6BacEba8535dd14d1"
+ verificationFacet = "0xaB84813cbf26Fd951CB3d7E33Dccb8995027e490"
+ entryPoint = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
+ facetRegistry = "0x9a95d201BB8F559771784D12c01F8084278c65E5"
+ defaultFallback = "0x522cDc7558b5f798dF5D61AB09B6D95Ebd342EF9"
+ bytecode = "0x60806040526040516104c83803806104c883398101604081905261002291610163565b6000858585858560405160240161003d959493929190610264565b60408051601f198184030181529181526020820180516001600160e01b0316634a93641760e01b1790525190915060009081906001600160a01b038a16906100869085906102c3565b600060405180830381855af49150503d80600081146100c1576040519150601f19603f3d011682016040523d82523d6000602084013e6100c6565b606091505b50915091508115806100e157506100dc816102df565b600114155b156100ff57604051636ff35f8960e01b815260040160405180910390fd5b505050505050505050610306565b80516001600160a01b038116811461012457600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561015a578181015183820152602001610142565b50506000910152565b60008060008060008060c0878903121561017c57600080fd5b6101858761010d565b95506101936020880161010d565b94506101a16040880161010d565b93506101af6060880161010d565b92506101bd6080880161010d565b60a08801519092506001600160401b03808211156101da57600080fd5b818901915089601f8301126101ee57600080fd5b81518181111561020057610200610129565b604051601f8201601f19908116603f0116810190838211818310171561022857610228610129565b816040528281528c602084870101111561024157600080fd5b61025283602083016020880161013f565b80955050505050509295509295509295565b600060018060a01b0380881683528087166020840152808616604084015280851660608401525060a0608083015282518060a08401526102ab8160c085016020870161013f565b601f01601f19169190910160c0019695505050505050565b600082516102d581846020870161013f565b9190910192915050565b80516020808301519190811015610300576000198160200360031b1b821691505b50919050565b6101b3806103156000396000f3fe60806040523661000b57005b600080356001600160e01b03191681527f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f6020819052604090912054819060601c806100cf576004838101546040516366ffd66360e11b81526000356001600160e01b031916928101929092526001600160a01b03169063cdffacc690602401602060405180830381865afa1580156100a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100cc919061014d565b90505b6001600160a01b0381166101295760405162461bcd60e51b815260206004820152601d60248201527f4261727a3a2046756e6374696f6e20646f6573206e6f74206578697374000000604482015260640160405180910390fd5b3660008037600080366000845af43d6000803e808015610148573d6000f35b3d6000fd5b60006020828403121561015f57600080fd5b81516001600160a01b038116811461017657600080fd5b939250505056fea2646970667358221220d35db061bb6ecdb7688c3674af669ce44d527cae4ded59214d06722d73da62be64736f6c63430008120033"
+ publicKey = "0xB5547FBdC56DCE45e1B8ef75569916D438e09c46"
+ salt = 123456
+ }
+ val result = WCBarz.getCounterfactualAddress(input.build().toByteArray())
+ assertEquals(result, "0xB91aaa96B138A1B1D94c9df4628187132c5F2bf1")
+ }
+
@Test
fun testGetFormattedSignature() {
val signature = Numeric.hexStringToByteArray("0x3044022012d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf0220256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca276")
@@ -126,7 +155,7 @@ class TestBarz {
sender = "0x1392Ae041BfBdBAA0cFF9234a0C8F64df97B7218"
preVerificationGas = ByteString.copyFrom("0xb708".toHexByteArray())
verificationGasLimit = ByteString.copyFrom("0x2DC6C0".toHexByteArray())
- initCode = ByteString.copyFrom(WCBarz.getInitCode(factoryAddress, publicKey, verificationFacet))
+ initCode = ByteString.copyFrom(WCBarz.getInitCode(factoryAddress, publicKey, verificationFacet, 0))
}.build()
transaction = Ethereum.Transaction.newBuilder().apply {
diff --git a/docs/registry.md b/docs/registry.md
index 1ae2fe4c8da..385273ff0ee 100644
--- a/docs/registry.md
+++ b/docs/registry.md
@@ -86,6 +86,7 @@ This list is generated from [./registry.json](../registry.json)
| 3030 | Hedera | HBAR | | |
| 5611 | OpBNB testnet | tBNB | | |
| 6060 | GoChain | GO | | |
+| 8453 | Base | ETH | | |
| 8964 | NULS | NULS | | |
| 14001 | WAX | WAXP | | |
| 18000 | Meter | MTR | | |
diff --git a/include/TrustWalletCore/TWBarz.h b/include/TrustWalletCore/TWBarz.h
index e68a6527c0e..3bc08ed31b4 100644
--- a/include/TrustWalletCore/TWBarz.h
+++ b/include/TrustWalletCore/TWBarz.h
@@ -30,7 +30,7 @@ TWString *_Nonnull TWBarzGetCounterfactualAddress(TWData *_Nonnull input);
/// \param verificationFacet Verification facet address
/// \return The address.
TW_EXPORT_STATIC_METHOD
-TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet);
+TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet, uint32_t salt);
/// Converts the original ASN-encoded signature from webauthn to the format accepted by Barz
///
diff --git a/include/TrustWalletCore/TWBitcoinFee.h b/include/TrustWalletCore/TWBitcoinFee.h
index 2d2da6ec359..33dc9c6c5ea 100644
--- a/include/TrustWalletCore/TWBitcoinFee.h
+++ b/include/TrustWalletCore/TWBitcoinFee.h
@@ -7,13 +7,19 @@
#pragma once
#include "TWData.h"
+#include "TWString.h"
TW_EXTERN_C_BEGIN
TW_EXPORT_CLASS
struct TWBitcoinFee;
+/// Calculates the fee of any Bitcoin transaction.
+///
+/// \param data: the signed transaction in its final form.
+/// \param satVb: the satoshis per vbyte amount. The passed on string is interpreted as a unit64_t.
+/// \returns the fee denominated in satoshis or nullptr if the transaction failed to be decoded.
TW_EXPORT_STATIC_METHOD
-uint64_t TWBitcoinFeeCalculateFee(TWData* _Nonnull data, uint64_t satVb);
+TWString* _Nullable TWBitcoinFeeCalculateFee(TWData* _Nonnull data, TWString* _Nonnull satVb);
TW_EXTERN_C_END
diff --git a/include/TrustWalletCore/TWCoinType.h b/include/TrustWalletCore/TWCoinType.h
index a762105c596..beef6628af1 100644
--- a/include/TrustWalletCore/TWCoinType.h
+++ b/include/TrustWalletCore/TWCoinType.h
@@ -170,6 +170,7 @@ enum TWCoinType {
TWCoinTypeAcalaEVM = 10000787,
TWCoinTypeOpBNBtestnet = 5611,
TWCoinTypeNeon = 245022934,
+ TWCoinTypeBase = 8453,
};
/// Returns the blockchain for a coin type.
diff --git a/registry.json b/registry.json
index 00fd6bd4cbd..e80fa59e5f0 100644
--- a/registry.json
+++ b/registry.json
@@ -350,6 +350,36 @@
"documentation": "https://docs.syscoin.org"
}
},
+ {
+ "id": "base",
+ "name": "Base",
+ "coinId": 8453,
+ "symbol": "ETH",
+ "decimals": 18,
+ "blockchain": "Ethereum",
+ "derivation": [
+ {
+ "path": "m/44'/60'/0'/0/0"
+ }
+ ],
+ "curve": "secp256k1",
+ "publicKeyType": "secp256k1Extended",
+ "chainId": "8453",
+ "addressHasher": "keccak256",
+ "explorer": {
+ "url": "https://basescan.org",
+ "txPath": "/tx/",
+ "accountPath": "/address/",
+ "sampleTx": "0x4acb15506b7696a2dfac4258f3f86392b4b2b717a3f316a8aa78509b2c3b6ab4",
+ "sampleAccount": "0xb8ff877ed78ba520ece21b1de7843a8a57ca47cb"
+ },
+ "info": {
+ "url": "https://base.mirror.xyz/",
+ "source": "https://github.com/base-org",
+ "rpc": "https://mainnet.base.org",
+ "documentation": "https://docs.base.org/"
+ }
+ },
{
"id": "ethereum",
"name": "Ethereum",
diff --git a/src/Aptos/Signer.cpp b/src/Aptos/Signer.cpp
index 18809c749cc..5c4b676583b 100644
--- a/src/Aptos/Signer.cpp
+++ b/src/Aptos/Signer.cpp
@@ -162,6 +162,15 @@ TransactionPayload tokenTransferPayload(const Proto::SigningInput& input) {
return payload;
}
+TransactionPayload tokenTransferCoinsPayload(const Proto::SigningInput& input) {
+ auto&& [args, argsJson] = commonTransferPayload(input.token_transfer_coins());
+ auto& function = input.token_transfer_coins().function();
+ TypeTag tokenTransferTag = {TypeTag::TypeTagVariant(TStructTag{.st = StructTag(Address(function.account_address()),
+ function.module(), function.name(), {})})};
+ TransactionPayload payload = EntryFunction(gAptosAccountModule, "transfer_coins", {tokenTransferTag}, args, argsJson);
+ return payload;
+}
+
TransactionPayload registerTokenPayload(const Proto::SigningInput& input) {
auto& function = input.register_token().function();
@@ -257,6 +266,9 @@ Proto::SigningOutput Signer::sign(const Proto::SigningInput& input) {
case Proto::SigningInput::kLiquidStakingMessage: {
return liquidStakingFunctor(input.liquid_staking_message());
}
+ case Proto::SigningInput::kTokenTransferCoins: {
+ return tokenTransferCoinsPayload(input);
+ }
case Proto::SigningInput::TRANSACTION_PAYLOAD_NOT_SET:
throw std::runtime_error("Transaction payload should be set");
}
diff --git a/src/Ethereum/ABI/Array.cpp b/src/Ethereum/ABI/Array.cpp
index 472f5a86e1f..9dc78a40d77 100644
--- a/src/Ethereum/ABI/Array.cpp
+++ b/src/Ethereum/ABI/Array.cpp
@@ -79,7 +79,7 @@ bool ParamArray::decode(const Data& encoded, size_t& offset_inout) {
// pad with first type
auto first = _params.getParamUnsafe(0);
for (size_t i = 0; i < len - n; i++) {
- _params.addParam(ParamFactory::make(first->getType()));
+ _params.addParam(first->clone());
}
}
@@ -105,7 +105,7 @@ bool ParamArray::setValueJson(const std::string& value) {
}
// make sure enough elements are in the array
while (_params.getCount() < valuesJson.size()) {
- addParam(ParamFactory::make(getProtoType()));
+ addParam(getProtoElem()->clone());
}
int cnt = 0;
for (const auto& e : valuesJson) {
@@ -133,6 +133,13 @@ std::string ParamArray::getExtraTypes(std::vector& ignoreList) cons
return (proto != nullptr) ? proto->getExtraTypes(ignoreList) : "";
}
+std::shared_ptr ParamArray::clone() const {
+ auto newArray = std::make_shared();
+ newArray->_params = _params.clone();
+ newArray->_proto = _proto->clone();
+ return newArray;
+}
+
void ParamArrayFix::encode(Data& data) const {
this->_params.encode(data);
}
@@ -156,6 +163,12 @@ bool ParamArrayFix::setValueJson(const std::string& value) {
return true;
}
+std::shared_ptr ParamArrayFix::clone() const {
+ auto newArray = std::make_shared();
+ newArray->_params = _params.clone();
+ return newArray;
+}
+
void ParamArrayFix::addParams(const Params& params) {
auto addParamFunctor = [this](auto&& param) {
if (param == nullptr) {
diff --git a/src/Ethereum/ABI/Array.h b/src/Ethereum/ABI/Array.h
index 8be902174e6..9a2e38bbd08 100644
--- a/src/Ethereum/ABI/Array.h
+++ b/src/Ethereum/ABI/Array.h
@@ -15,7 +15,7 @@ namespace TW::Ethereum::ABI {
/// Dynamic array of the same types, "[]"
/// Normally has at least one element. Empty array can have prototype set so its type is known.
/// Empty with no prototype is possible, but should be avoided.
-class ParamArray : public ParamCollection {
+class ParamArray final : public ParamCollection {
private:
ParamSet _params;
std::shared_ptr _proto; // an optional prototype element, determines the array type, useful in empty array case
@@ -36,15 +36,17 @@ class ParamArray : public ParamCollection {
void addParams(const std::vector>& params);
void setProto(const std::shared_ptr& proto) { _proto = proto; }
std::shared_ptr getParam(int paramIndex) { return _params.getParamUnsafe(paramIndex); }
- virtual std::string getType() const { return getProtoType() + "[]"; }
- virtual size_t getSize() const;
- virtual bool isDynamic() const { return true; }
- virtual size_t getCount() const { return _params.getCount(); }
- virtual void encode(Data& data) const;
- virtual bool decode(const Data& encoded, size_t& offset_inout);
- virtual bool setValueJson(const std::string& value);
- virtual Data hashStruct() const;
- virtual std::string getExtraTypes(std::vector& ignoreList) const;
+
+ std::string getType() const override { return getProtoType() + "[]"; }
+ size_t getSize() const override;
+ bool isDynamic() const override { return true; }
+ size_t getCount() const override { return _params.getCount(); }
+ void encode(Data& data) const override;
+ bool decode(const Data& encoded, size_t& offset_inout) override;
+ bool setValueJson(const std::string& value) override;
+ Data hashStruct() const override;
+ std::string getExtraTypes(std::vector& ignoreList) const override;
+ std::shared_ptr clone() const override;
};
/// Fixed-size array of the same type e.g, "type[4]"
@@ -53,20 +55,23 @@ class ParamArrayFix final : public ParamCollection {
//! Public Definitions
using Params = std::vector>;
- //! Public constructor
+ //! Public constructors
+ ParamArrayFix() = default;
+
explicit ParamArrayFix(const Params& params) noexcept(false)
: ParamCollection() {
this->addParams(params);
}
//! Public member methods
- [[nodiscard]] std::size_t getCount() const final { return _params.getCount(); }
- [[nodiscard]] size_t getSize() const final { return _params.getSize(); }
- [[nodiscard]] bool isDynamic() const final { return false; }
- [[nodiscard]] std::string getType() const final { return _params.getParamUnsafe(0)->getType() + "[" + std::to_string(_params.getCount()) + "]"; }
- void encode(Data& data) const final;
- bool decode(const Data& encoded, size_t& offset_inout) final;
- bool setValueJson(const std::string& value) final;
+ [[nodiscard]] std::size_t getCount() const override { return _params.getCount(); }
+ [[nodiscard]] size_t getSize() const override { return _params.getSize(); }
+ [[nodiscard]] bool isDynamic() const override { return false; }
+ [[nodiscard]] std::string getType() const override { return _params.getParamUnsafe(0)->getType() + "[" + std::to_string(_params.getCount()) + "]"; }
+ void encode(Data& data) const override;
+ bool decode(const Data& encoded, size_t& offset_inout) override;
+ bool setValueJson(const std::string& value) override;
+ std::shared_ptr clone() const override;
private:
//! Private member functions
diff --git a/src/Ethereum/ABI/Bytes.cpp b/src/Ethereum/ABI/Bytes.cpp
index cb1277b96f9..5cbee7fc970 100644
--- a/src/Ethereum/ABI/Bytes.cpp
+++ b/src/Ethereum/ABI/Bytes.cpp
@@ -56,6 +56,10 @@ Data ParamByteArray::hashStruct() const {
return Hash::keccak256(_bytes);
}
+std::shared_ptr ParamByteArray::clone() const {
+ return std::make_shared(_bytes);
+}
+
void ParamByteArrayFix::setVal(const Data& val) {
if (val.size() > _n) { // crop right
_bytes = subData(val, 0, _n);
@@ -105,6 +109,10 @@ Data ParamByteArrayFix::hashStruct() const {
return ParamBase::hashStruct();
}
+std::shared_ptr ParamByteArrayFix::clone() const {
+ return std::make_shared(_n, _bytes);
+}
+
void ParamString::encodeString(const std::string& decoded, Data& data) {
auto bytes = Data(decoded.begin(), decoded.end());
ParamByteArray::encodeBytes(bytes, data);
@@ -126,4 +134,8 @@ Data ParamString::hashStruct() const {
return hash;
}
+std::shared_ptr ParamString::clone() const {
+ return std::make_shared(_str);
+}
+
} // namespace TW::Ethereum::ABI
diff --git a/src/Ethereum/ABI/Bytes.h b/src/Ethereum/ABI/Bytes.h
index a3695a813b5..3fc92f4c78e 100644
--- a/src/Ethereum/ABI/Bytes.h
+++ b/src/Ethereum/ABI/Bytes.h
@@ -13,7 +13,7 @@
namespace TW::Ethereum::ABI {
/// Dynamic array of bytes "bytes"
-class ParamByteArray: public ParamCollection
+class ParamByteArray final: public ParamCollection
{
private:
Data _bytes;
@@ -22,22 +22,23 @@ class ParamByteArray: public ParamCollection
ParamByteArray(const Data& val) : ParamCollection() { setVal(val); }
void setVal(const Data& val) { _bytes = val; }
const Data& getVal() const { return _bytes; }
- virtual std::string getType() const { return "bytes"; };
- virtual size_t getSize() const { return 32 + ValueEncoder::paddedTo32(_bytes.size()); }
- virtual bool isDynamic() const { return true; }
- virtual size_t getCount() const { return _bytes.size(); }
+ std::string getType() const override { return "bytes"; };
+ size_t getSize() const override { return 32 + ValueEncoder::paddedTo32(_bytes.size()); }
+ bool isDynamic() const override { return true; }
+ size_t getCount() const override { return _bytes.size(); }
static void encodeBytes(const Data& bytes, Data& data);
- virtual void encode(Data& data) const { encodeBytes(_bytes, data); }
+ void encode(Data& data) const override { encodeBytes(_bytes, data); }
static bool decodeBytes(const Data& encoded, Data& decoded, size_t& offset_inout);
- virtual bool decode(const Data& encoded, size_t& offset_inout) {
+ bool decode(const Data& encoded, size_t& offset_inout) override {
return decodeBytes(encoded, _bytes, offset_inout);
}
- virtual bool setValueJson(const std::string& value);
- virtual Data hashStruct() const;
+ bool setValueJson(const std::string& value) override;
+ Data hashStruct() const override;
+ std::shared_ptr clone() const override;
};
/// Fixed-size array of bytes, "bytes"
-class ParamByteArrayFix: public ParamCollection
+class ParamByteArrayFix final: public ParamCollection
{
private:
size_t _n;
@@ -47,41 +48,43 @@ class ParamByteArrayFix: public ParamCollection
ParamByteArrayFix(size_t n, const Data& val): ParamCollection(), _n(n), _bytes(Data(_n)) { setVal(val); }
void setVal(const Data& val);
const std::vector& getVal() const { return _bytes; }
- virtual std::string getType() const { return "bytes" + std::to_string(_n); };
- virtual size_t getSize() const { return ValueEncoder::paddedTo32(_bytes.size()); }
- virtual bool isDynamic() const { return false; }
- virtual size_t getCount() const { return _bytes.size(); }
- virtual void encode(Data& data) const;
+ std::string getType() const override { return "bytes" + std::to_string(_n); };
+ size_t getSize() const override { return ValueEncoder::paddedTo32(_bytes.size()); }
+ bool isDynamic() const override { return false; }
+ size_t getCount() const override { return _bytes.size(); }
+ void encode(Data& data) const override;
static bool decodeBytesFix(const Data& encoded, size_t n, Data& decoded, size_t& offset_inout);
- virtual bool decode(const Data& encoded, size_t& offset_inout) {
+ bool decode(const Data& encoded, size_t& offset_inout) override {
return decodeBytesFix(encoded, _n, _bytes, offset_inout);
}
- virtual bool setValueJson(const std::string& value);
- virtual Data hashStruct() const;
+ bool setValueJson(const std::string& value) override;
+ Data hashStruct() const override;
+ std::shared_ptr clone() const override;
};
/// Var-length string parameter
-class ParamString: public ParamCollection
+class ParamString final: public ParamCollection
{
private:
std::string _str;
public:
ParamString() = default;
- ParamString(std::string val): ParamCollection() { setVal(val); }
+ ParamString(const std::string& val): ParamCollection() { setVal(val); }
void setVal(const std::string& val) { _str = val; }
const std::string& getVal() const { return _str; }
- virtual std::string getType() const { return "string"; };
- virtual size_t getSize() const { return 32 + ValueEncoder::paddedTo32(_str.size()); }
- virtual bool isDynamic() const { return true; }
- virtual size_t getCount() const { return _str.size(); }
+ std::string getType() const override { return "string"; };
+ size_t getSize() const override { return 32 + ValueEncoder::paddedTo32(_str.size()); }
+ bool isDynamic() const override { return true; }
+ size_t getCount() const override { return _str.size(); }
static void encodeString(const std::string& decoded, Data& data);
- virtual void encode(Data& data) const { ParamString::encodeString(_str, data); }
+ void encode(Data& data) const override { ParamString::encodeString(_str, data); }
static bool decodeString(const Data& encoded, std::string& decoded, size_t& offset_inout);
- virtual bool decode(const Data& encoded, size_t& offset_inout) {
+ bool decode(const Data& encoded, size_t& offset_inout) override {
return decodeString(encoded, _str, offset_inout);
}
- virtual bool setValueJson(const std::string& value) { _str = value; return true; }
- virtual Data hashStruct() const;
+ bool setValueJson(const std::string& value) override { _str = value; return true; }
+ Data hashStruct() const override;
+ std::shared_ptr clone() const override;
};
} // namespace TW::Ethereum::ABI
diff --git a/src/Ethereum/ABI/ParamAddress.cpp b/src/Ethereum/ABI/ParamAddress.cpp
index df29b67763e..1707f9f2084 100644
--- a/src/Ethereum/ABI/ParamAddress.cpp
+++ b/src/Ethereum/ABI/ParamAddress.cpp
@@ -11,13 +11,17 @@
namespace TW::Ethereum::ABI {
Data ParamAddress::getData() const {
- Data data = store(getVal(), bytes);
+ Data data = store(_val.getVal(), bytes);
return data;
}
bool ParamAddress::setValueJson(const std::string& value) {
- setVal(load(parse_hex(value)));
+ _val.setVal(load(parse_hex(value)));
return true;
}
+std::shared_ptr ParamAddress::clone() const {
+ return std::make_shared(getData());
+}
+
} // namespace TW::Ethereum::ABI
diff --git a/src/Ethereum/ABI/ParamAddress.h b/src/Ethereum/ABI/ParamAddress.h
index 38b05bd342c..c9ae0fa9d16 100644
--- a/src/Ethereum/ABI/ParamAddress.h
+++ b/src/Ethereum/ABI/ParamAddress.h
@@ -12,16 +12,23 @@
namespace TW::Ethereum::ABI {
/// 160-bit Address parameter, "address". Padded to the right, treated like ParamUInt160
-class ParamAddress: public ParamUIntN
+class ParamAddress final: public ParamBase
{
+private:
+ ParamUIntN _val;
public:
static const size_t bytes = 20;
- ParamAddress(): ParamUIntN(bytes * 8) {}
- ParamAddress(const Data& val): ParamUIntN(bytes * 8, load(val)) {}
- virtual std::string getType() const { return "address"; };
+ ParamAddress(): _val(bytes * 8) {}
+ explicit ParamAddress(const Data& val): _val(bytes * 8, load(val)) {}
+ std::string getType() const override { return "address"; };
+ size_t getSize() const override { return _val.getSize(); }
+ bool isDynamic() const override { return _val.isDynamic(); }
+ void encode(Data& data) const override { _val.encode(data); }
+ bool decode(const Data& encoded, size_t& offset_inout) override { return _val.decode(encoded, offset_inout); }
// get the value as (20-byte) byte array (as opposed to uint256_t)
Data getData() const;
- virtual bool setValueJson(const std::string& value);
+ bool setValueJson(const std::string& value) override;
+ std::shared_ptr clone() const override;
};
} // namespace TW::Ethereum::ABI
diff --git a/src/Ethereum/ABI/ParamBase.h b/src/Ethereum/ABI/ParamBase.h
index 673d4c43047..11039de5a75 100644
--- a/src/Ethereum/ABI/ParamBase.h
+++ b/src/Ethereum/ABI/ParamBase.h
@@ -9,6 +9,7 @@
#include "Data.h"
#include
+#include
namespace TW::Ethereum::ABI {
@@ -27,6 +28,9 @@ class ParamBase
virtual Data hashStruct() const;
// Helper for EIP712 encoding; provide full type of all used types (recursively). Default is empty implementation.
virtual std::string getExtraTypes([[maybe_unused]] std::vector& ignoreList) const { return ""; }
+ // Creates a copy of this element.
+ // This method **must** be implemented in a `final` class only.
+ virtual std::shared_ptr clone() const = 0;
};
/// Collection of parameters base class
diff --git a/src/Ethereum/ABI/ParamNumber.h b/src/Ethereum/ABI/ParamNumber.h
index 05e10753b47..a9b9ea6f631 100644
--- a/src/Ethereum/ABI/ParamNumber.h
+++ b/src/Ethereum/ABI/ParamNumber.h
@@ -31,12 +31,12 @@ inline bool decode(const Data& encoded, uint256_t& decoded, size_t& offset_inout
}
/// Generic parameter class for numeric types, like bool, uint32, int64, etc. All are stored on 256 bits.
-template
+template
class ParamNumberType : public ParamBase
{
public:
ParamNumberType() = default;
- ParamNumberType(T val) { _val = val; }
+ explicit ParamNumberType(const T& val): _val(val) { }
void setVal(T val) { _val = val; }
T getVal() const { return _val; }
virtual std::string getType() const = 0;
@@ -63,108 +63,119 @@ class ParamNumberType : public ParamBase
T _val;
};
-class ParamUInt256 : public ParamNumberType
+class ParamUInt256 final : public ParamNumberType
{
public:
ParamUInt256() : ParamNumberType(uint256_t(0)) {}
- ParamUInt256(uint256_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "uint256"; }
+ explicit ParamUInt256(const uint256_t& val) : ParamNumberType(val) {}
+ std::string getType() const override { return "uint256"; }
uint256_t getVal() const { return ParamNumberType::getVal(); }
- virtual bool setValueJson(const std::string& value) { return setUInt256FromValueJson(_val, value); }
+ bool setValueJson(const std::string& value) override { return setUInt256FromValueJson(_val, value); }
static bool setUInt256FromValueJson(uint256_t& dest, const std::string& value);
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamInt256 : public ParamNumberType
+class ParamInt256 final : public ParamNumberType
{
public:
ParamInt256() : ParamNumberType(int256_t(0)) {}
- ParamInt256(int256_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "int256"; }
+ explicit ParamInt256(const int256_t& val) : ParamNumberType(val) {}
+ std::string getType() const override { return "int256"; }
int256_t getVal() const { return ParamNumberType::getVal(); }
- virtual bool setValueJson(const std::string& value) { return setInt256FromValueJson(_val, value); }
+ bool setValueJson(const std::string& value) override { return setInt256FromValueJson(_val, value); }
static bool setInt256FromValueJson(int256_t& dest, const std::string& value);
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamBool : public ParamNumberType
+class ParamBool final : public ParamNumberType
{
public:
ParamBool() : ParamNumberType(false) {}
- ParamBool(bool val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "bool"; }
+ explicit ParamBool(bool val) : ParamNumberType(val) {}
+ std::string getType() const override { return "bool"; }
bool getVal() const { return ParamNumberType::getVal(); }
- virtual bool setValueJson(const std::string& value);
+ bool setValueJson(const std::string& value) override;
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamUInt8 : public ParamNumberType
+class ParamUInt8 final : public ParamNumberType
{
public:
ParamUInt8() : ParamNumberType(0) {}
- ParamUInt8(uint8_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "uint8"; }
- virtual bool setValueJson(const std::string& value);
+ explicit ParamUInt8(uint8_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "uint8"; }
+ bool setValueJson(const std::string& value) override;
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamInt8 : public ParamNumberType
+class ParamInt8 final : public ParamNumberType
{
public:
ParamInt8() : ParamNumberType(0) {}
- ParamInt8(int8_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "int8"; }
- virtual bool setValueJson(const std::string& value);
+ explicit ParamInt8(int8_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "int8"; }
+ bool setValueJson(const std::string& value) override;
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamUInt16 : public ParamNumberType
+class ParamUInt16 final : public ParamNumberType
{
public:
ParamUInt16() : ParamNumberType(0) {}
- ParamUInt16(uint16_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "uint16"; }
+ explicit ParamUInt16(uint16_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "uint16"; }
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamInt16 : public ParamNumberType
+class ParamInt16 final : public ParamNumberType
{
public:
ParamInt16() : ParamNumberType(0) {}
- ParamInt16(int16_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "int16"; }
+ explicit ParamInt16(int16_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "int16"; }
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamUInt32 : public ParamNumberType
+class ParamUInt32 final : public ParamNumberType
{
public:
ParamUInt32() : ParamNumberType(0) {}
- ParamUInt32(uint32_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "uint32"; }
+ explicit ParamUInt32(uint32_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "uint32"; }
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamInt32 : public ParamNumberType
+class ParamInt32 final : public ParamNumberType
{
public:
ParamInt32() : ParamNumberType(0) {}
- ParamInt32(int32_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "int32"; }
+ explicit ParamInt32(int32_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "int32"; }
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamUInt64 : public ParamNumberType
+class ParamUInt64 final : public ParamNumberType
{
public:
ParamUInt64() : ParamNumberType(0) {}
- ParamUInt64(uint64_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "uint64"; }
+ explicit ParamUInt64(uint64_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "uint64"; }
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
-class ParamInt64 : public ParamNumberType
+class ParamInt64 final : public ParamNumberType
{
public:
ParamInt64() : ParamNumberType(0) {}
- ParamInt64(int64_t val) : ParamNumberType(val) {}
- virtual std::string getType() const { return "int64"; }
+ explicit ParamInt64(int64_t val) : ParamNumberType(val) {}
+ std::string getType() const override { return "int64"; }
+ std::shared_ptr clone() const override { return std::make_shared(_val); }
};
/// Generic parameter class for all other bit sizes, like UInt24, 40, 48, ... 248.
/// For predefined sizes (8, 16, 32, 64, 256) use the sepcial types like UInt32.
/// Stored on 256 bits.
-class ParamUIntN : public ParamBase
+class ParamUIntN final : public ParamBase
{
public:
const size_t bits;
@@ -172,16 +183,17 @@ class ParamUIntN : public ParamBase
ParamUIntN(size_t bits_in, uint256_t val) : bits(bits_in) { init(); setVal(val); }
void setVal(uint256_t val);
uint256_t getVal() const { return _val; }
- virtual std::string getType() const { return "uint" + std::to_string(bits); }
- virtual size_t getSize() const { return ValueEncoder::encodedIntSize; }
- virtual bool isDynamic() const { return false; }
- virtual void encode(Data& data) const { ValueEncoder::encodeUInt256(_val, data); }
+ std::string getType() const override { return "uint" + std::to_string(bits); }
+ size_t getSize() const override { return ValueEncoder::encodedIntSize; }
+ bool isDynamic() const override { return false; }
+ void encode(Data& data) const override { ValueEncoder::encodeUInt256(_val, data); }
static bool decodeNumber(const Data& encoded, uint256_t& decoded, size_t& offset_inout) {
return ABI::decode(encoded, decoded, offset_inout);
}
- virtual bool decode(const Data& encoded, size_t& offset_inout);
+ bool decode(const Data& encoded, size_t& offset_inout) override;
static uint256_t maskForBits(size_t bits);
- virtual bool setValueJson(const std::string& value) { return ParamUInt256::setUInt256FromValueJson(_val, value); }
+ bool setValueJson(const std::string& value) override { return ParamUInt256::setUInt256FromValueJson(_val, value); }
+ std::shared_ptr clone() const override { return std::make_shared(bits, _val); }
private:
void init();
@@ -192,7 +204,7 @@ class ParamUIntN : public ParamBase
/// Generic parameter class for all other bit sizes, like Int24, 40, 48, ... 248.
/// For predefined sizes (8, 16, 32, 64, 256) use the sepcial types like Int32.
/// Stored on 256 bits.
-class ParamIntN : public ParamBase
+class ParamIntN final : public ParamBase
{
public:
const size_t bits;
@@ -200,13 +212,14 @@ class ParamIntN : public ParamBase
ParamIntN(size_t bits_in, int256_t val) : bits(bits_in) { init(); setVal(val); }
void setVal(int256_t val);
int256_t getVal() const { return _val; }
- virtual std::string getType() const { return "int" + std::to_string(bits); }
- virtual size_t getSize() const { return ValueEncoder::encodedIntSize; }
- virtual bool isDynamic() const { return false; }
- virtual void encode(Data& data) const { ValueEncoder::encodeUInt256((uint256_t)_val, data); }
+ std::string getType() const override { return "int" + std::to_string(bits); }
+ size_t getSize() const override { return ValueEncoder::encodedIntSize; }
+ bool isDynamic() const override { return false; }
+ void encode(Data& data) const override { ValueEncoder::encodeUInt256((uint256_t)_val, data); }
static bool decodeNumber(const Data& encoded, int256_t& decoded, size_t& offset_inout);
- virtual bool decode(const Data& encoded, size_t& offset_inout);
- virtual bool setValueJson(const std::string& value) { return ParamInt256::setInt256FromValueJson(_val, value); }
+ bool decode(const Data& encoded, size_t& offset_inout) override;
+ bool setValueJson(const std::string& value) override { return ParamInt256::setInt256FromValueJson(_val, value); }
+ std::shared_ptr clone() const override { return std::make_shared(bits, _val); }
private:
void init();
diff --git a/src/Ethereum/ABI/ParamStruct.cpp b/src/Ethereum/ABI/ParamStruct.cpp
index ac4de7b0ccb..680037ceb3d 100644
--- a/src/Ethereum/ABI/ParamStruct.cpp
+++ b/src/Ethereum/ABI/ParamStruct.cpp
@@ -27,6 +27,10 @@ std::string ParamNamed::getType() const {
return _param->getType() + " " + _name;
}
+std::shared_ptr ParamNamed::cloneNamed() const {
+ return std::make_shared(_name, _param->clone());
+}
+
ParamSetNamed::~ParamSetNamed() {
_params.clear();
}
@@ -104,6 +108,14 @@ std::shared_ptr ParamSetNamed::findParamByName(const std::string& na
return nullptr;
}
+ParamSetNamed ParamSetNamed::clone() const {
+ ParamSetNamed newSet;
+ for (const auto& p : _params) {
+ newSet.addParam(p->cloneNamed());
+ }
+ return newSet;
+}
+
Data ParamStruct::hashType() const {
return Hash::keccak256(TW::data(encodeType()));
}
@@ -138,6 +150,10 @@ std::string ParamStruct::getExtraTypes(std::vector& ignoreList) con
return types;
}
+std::shared_ptr ParamStruct::clone() const {
+ return std::make_shared(_name, _params.clone());
+}
+
Data ParamStruct::hashStructJson(const std::string& messageJson) {
auto message = json::parse(messageJson, nullptr, false);
if (message.is_discarded()) {
diff --git a/src/Ethereum/ABI/ParamStruct.h b/src/Ethereum/ABI/ParamStruct.h
index c043e588796..64b550d2cfb 100644
--- a/src/Ethereum/ABI/ParamStruct.h
+++ b/src/Ethereum/ABI/ParamStruct.h
@@ -15,25 +15,27 @@
namespace TW::Ethereum::ABI {
/// A named parameter.
-class ParamNamed: public ParamBase
+class ParamNamed final : public ParamBase
{
public:
std::string _name;
std::shared_ptr _param;
public:
- ParamNamed(const std::string& name, std::shared_ptr param): _name(name), _param(param) {}
-
- virtual std::string getName() const { return _name; }
- virtual std::shared_ptr getParam() const { return _param; }
- virtual std::string getType() const;
- virtual size_t getSize() const { return _param->getSize(); }
- virtual bool isDynamic() const { return _param->isDynamic(); }
- virtual void encode(Data& data) const { return _param->encode(data); }
- virtual bool decode(const Data& encoded, size_t& offset_inout) { return _param->decode(encoded, offset_inout); }
- virtual bool setValueJson(const std::string& value) { return _param->setValueJson(value); }
- virtual Data hashStruct() const { return _param->hashStruct(); }
- virtual std::string getExtraTypes(std::vector& ignoreList) const { return _param->getExtraTypes(ignoreList); }
+ explicit ParamNamed(const std::string& name, std::shared_ptr param): _name(name), _param(param) {}
+
+ std::string getName() const { return _name; }
+ std::shared_ptr getParam() const { return _param; }
+ std::string getType() const override;
+ size_t getSize() const override { return _param->getSize(); }
+ bool isDynamic() const override { return _param->isDynamic(); }
+ void encode(Data& data) const override { return _param->encode(data); }
+ bool decode(const Data& encoded, size_t& offset_inout) override { return _param->decode(encoded, offset_inout); }
+ bool setValueJson(const std::string& value) override { return _param->setValueJson(value); }
+ Data hashStruct() const override { return _param->hashStruct(); }
+ std::string getExtraTypes(std::vector& ignoreList) const override { return _param->getExtraTypes(ignoreList); }
+ std::shared_ptr clone() const override { return cloneNamed(); }
+ std::shared_ptr cloneNamed() const;
};
/// A collection of named parameters. See also: ParamStruct
@@ -56,10 +58,11 @@ class ParamSetNamed {
Data encodeHashes() const;
std::string getExtraTypes(std::vector& ignoreList) const;
std::shared_ptr findParamByName(const std::string& name) const;
+ ParamSetNamed clone() const;
};
/// A named structure (set of parameters plus a type name).
-class ParamStruct: public ParamCollection
+class ParamStruct final : public ParamCollection
{
private:
std::string _name;
@@ -68,12 +71,13 @@ class ParamStruct: public ParamCollection
public:
ParamStruct() = default;
ParamStruct(const std::string& name, const std::vector>& params) : ParamCollection(), _name(name), _params(ParamSetNamed(params)) {}
+ ParamStruct(const std::string& name, ParamSetNamed&& params) : ParamCollection(), _name(name), _params(std::move(params)) {}
- std::string getType() const { return _name; }
+ std::string getType() const override { return _name; }
const ParamSetNamed& getParams() const { return _params; }
/// Compute the hash of a struct, used for signing, according to EIP712
- virtual Data hashStruct() const;
+ Data hashStruct() const override;
/// Get full type, extended by used sub-types, of the form 'Mail(Person from,Person to,string contents)Person(string name,address wallet)'
std::string encodeType() const {
std::vector ignoreList;
@@ -82,14 +86,15 @@ class ParamStruct: public ParamCollection
/// Get the hash of the full type.
Data hashType() const;
- virtual size_t getSize() const { return _params.getCount(); }
- virtual bool isDynamic() const { return true; }
- virtual size_t getCount() const { return _params.getCount(); }
- virtual void encode([[maybe_unused]] Data& data) const {}
- virtual bool decode([[maybe_unused]] const Data& encoded, [[maybe_unused]] size_t& offset_inout) { return true; }
- virtual bool setValueJson([[maybe_unused]] const std::string& value) { return false; } // see makeStruct
+ size_t getSize() const override { return _params.getCount(); }
+ bool isDynamic() const override { return true; }
+ size_t getCount() const override { return _params.getCount(); }
+ void encode([[maybe_unused]] Data& data) const override {}
+ bool decode([[maybe_unused]] const Data& encoded, [[maybe_unused]] size_t& offset_inout) override { return true; }
+ bool setValueJson([[maybe_unused]] const std::string& value) override { return false; } // see makeStruct
Data encodeHashes() const;
- virtual std::string getExtraTypes(std::vector& ignoreList) const;
+ std::string getExtraTypes(std::vector& ignoreList) const override;
+ std::shared_ptr clone() const override;
std::shared_ptr findParamByName(const std::string& name) const { return _params.findParamByName(name); }
/// Compute the hash of a struct, used for signing, according to EIP712 ("v4").
diff --git a/src/Ethereum/ABI/Parameters.cpp b/src/Ethereum/ABI/Parameters.cpp
index b3eeb61ca04..973443fa540 100644
--- a/src/Ethereum/ABI/Parameters.cpp
+++ b/src/Ethereum/ABI/Parameters.cpp
@@ -128,28 +128,37 @@ void ParamSet::encode(Data& data) const {
}
bool ParamSet::decode(const Data& encoded, size_t& offset_inout) {
- // pass 1: small values
- for (auto p : _params) {
+ size_t arrayOffset = offset_inout;
+
+ for (const auto& p : _params) {
+ // Decode a dynamic element.
if (p->isDynamic()) {
uint256_t index;
if (!ABI::decode(encoded, index, offset_inout)) {
return false;
}
- // index is read but not used
- } else {
- if (!p->decode(encoded, offset_inout)) {
+
+ // Check if length is in the size_t range.
+ auto indexSize = static_cast(index);
+ if (indexSize != index) {
return false;
}
- }
- }
- // pass2: large values
- for (auto p : _params) {
- if (p->isDynamic()) {
- if (!p->decode(encoded, offset_inout)) {
+
+ // Calculate an offset relative to the beginning of this array.
+ size_t newOffset = arrayOffset + indexSize;
+ if (!p->decode(encoded, newOffset)) {
return false;
}
+
+ continue;
+ }
+
+ // Otherwise decode a static element, e.g `p->isDynamic() == false`.
+ if (!p->decode(encoded, offset_inout)) {
+ return false;
}
}
+
return true;
}
@@ -161,6 +170,15 @@ Data ParamSet::encodeHashes() const {
return hashes;
}
+ParamSet ParamSet::clone() const {
+ ParamSet newSet;
+ for (const auto& p : _params) {
+ newSet.addParam(p->clone());
+ }
+
+ return newSet;
+}
+
Data Parameters::hashStruct() const {
Data hash(32);
Data hashes = _params.encodeHashes();
@@ -170,4 +188,10 @@ Data Parameters::hashStruct() const {
return hash;
}
+std::shared_ptr Parameters::clone() const {
+ auto newParams = std::make_shared();
+ newParams->_params = _params.clone();
+ return newParams;
+}
+
} // namespace TW::Ethereum::ABI
diff --git a/src/Ethereum/ABI/Parameters.h b/src/Ethereum/ABI/Parameters.h
index 30aabf3d340..cc6d0844cd7 100644
--- a/src/Ethereum/ABI/Parameters.h
+++ b/src/Ethereum/ABI/Parameters.h
@@ -40,13 +40,15 @@ class ParamSet {
virtual void encode(Data& data) const;
virtual bool decode(const Data& encoded, size_t& offset_inout);
Data encodeHashes() const;
+ /// Creates a copy of this set with exactly the same params.
+ ParamSet clone() const;
private:
size_t getHeadSize() const;
};
/// Collection of different parameters, dynamic length, "(,,...)".
-class Parameters: public ParamCollection
+class Parameters final : public ParamCollection
{
private:
ParamSet _params;
@@ -57,14 +59,15 @@ class Parameters: public ParamCollection
void addParam(const std::shared_ptr& param) { _params.addParam(param); }
void addParams(const std::vector>& params) { _params.addParams(params); }
std::shared_ptr getParam(size_t paramIndex) const { return _params.getParamUnsafe(paramIndex); }
- virtual std::string getType() const { return _params.getType(); }
- virtual size_t getSize() const { return _params.getSize(); }
- virtual bool isDynamic() const { return true; }
- virtual size_t getCount() const { return _params.getCount(); }
- virtual void encode(Data& data) const { _params.encode(data); }
- virtual bool decode(const Data& encoded, size_t& offset_inout) { return _params.decode(encoded, offset_inout); }
- virtual bool setValueJson([[maybe_unused]] const std::string& value) { return false; }
- virtual Data hashStruct() const;
+ std::string getType() const override { return _params.getType(); }
+ size_t getSize() const override { return _params.getSize(); }
+ bool isDynamic() const override { return true; }
+ size_t getCount() const override { return _params.getCount(); }
+ void encode(Data& data) const override { _params.encode(data); }
+ bool decode(const Data& encoded, size_t& offset_inout) override { return _params.decode(encoded, offset_inout); }
+ bool setValueJson([[maybe_unused]] const std::string& value) override { return false; }
+ Data hashStruct() const override;
+ std::shared_ptr clone() const override;
};
} // namespace TW::Ethereum::ABI
diff --git a/src/Ethereum/ABI/Tuple.cpp b/src/Ethereum/ABI/Tuple.cpp
index 5f36ac33024..1f661b4aeca 100644
--- a/src/Ethereum/ABI/Tuple.cpp
+++ b/src/Ethereum/ABI/Tuple.cpp
@@ -14,4 +14,10 @@ int ParamTuple::addParam(std::shared_ptr param) {
return _params.addParam(param);
}
+std::shared_ptr ParamTuple::clone() const {
+ auto newTuple = std::make_shared();
+ newTuple->_params = _params.clone();
+ return newTuple;
+}
+
} // namespace TW::Ethereum::ABI
\ No newline at end of file
diff --git a/src/Ethereum/ABI/Tuple.h b/src/Ethereum/ABI/Tuple.h
index 6c8df69a789..2911703987e 100644
--- a/src/Ethereum/ABI/Tuple.h
+++ b/src/Ethereum/ABI/Tuple.h
@@ -13,13 +13,13 @@
namespace TW::Ethereum::ABI {
/// A Tuple is a collection of parameters
-class ParamTuple: public ParamCollection
+class ParamTuple final : public ParamCollection
{
public:
ParamSet _params;
- ParamTuple() {}
- ParamTuple(const std::vector>& params) : _params(ParamSet(params)) {}
+ ParamTuple() = default;
+ explicit ParamTuple(const std::vector>& params) : _params(ParamSet(params)) {}
/// Add a parameter. Returns the index of the parameter.
int addParam(std::shared_ptr param);
@@ -28,14 +28,15 @@ class ParamTuple: public ParamCollection
return _params.getParam(paramIndex, param_out);
}
/// Return the type signature, of the form "(int32,uint256)"
- std::string getType() const { return _params.getType(); }
-
- virtual size_t getSize() const { return _params.getSize(); }
- virtual bool isDynamic() const { return _params.isDynamic(); }
- virtual void encode(Data& data) const { return _params.encode(data); }
- virtual bool decode(const Data& encoded, size_t& offset_inout) { return _params.decode(encoded, offset_inout); }
- virtual bool setValueJson([[maybe_unused]] const std::string& value) { return false; }
- virtual size_t getCount() const { return _params.getCount(); }
+ std::string getType() const override { return _params.getType(); }
+
+ size_t getSize() const override { return _params.getSize(); }
+ bool isDynamic() const override { return _params.isDynamic(); }
+ void encode(Data& data) const override { return _params.encode(data); }
+ bool decode(const Data& encoded, size_t& offset_inout) override { return _params.decode(encoded, offset_inout); }
+ bool setValueJson([[maybe_unused]] const std::string& value) override { return false; }
+ size_t getCount() const override { return _params.getCount(); }
+ std::shared_ptr clone() const override;
};
} // namespace TW::Ethereum::ABI
diff --git a/src/Ethereum/Barz.cpp b/src/Ethereum/Barz.cpp
index 9cfbd0c0d49..e6cc3e92c56 100644
--- a/src/Ethereum/Barz.cpp
+++ b/src/Ethereum/Barz.cpp
@@ -9,7 +9,6 @@
#include "EIP1014.h"
#include "Hash.h"
#include "HexCoding.h"
-#include
#include "../proto/Barz.pb.h"
#include "AsnParser.h"
#include "Base64.h"
@@ -35,15 +34,15 @@ std::string getCounterfactualAddress(const Proto::ContractAddressInput input) {
append(initCode, encoded);
const Data initCodeHash = Hash::keccak256(initCode);
- const Data salt(32, 0);
+ Data salt = store(input.salt(), 32);
return Ethereum::checksumed(Ethereum::Address(hexEncoded(Ethereum::create2Address(input.factory(), salt, initCodeHash))));
}
-Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet) {
+Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet, const uint32_t salt) {
auto createAccountFunc = Ethereum::ABI::Function("createAccount", ParamCollection{
std::make_shared(parse_hex(verificationFacet)),
std::make_shared(publicKey.bytes),
- std::make_shared(0)});
+ std::make_shared(salt)});
Data createAccountFuncEncoded;
createAccountFunc.encode(createAccountFuncEncoded);
diff --git a/src/Ethereum/Barz.h b/src/Ethereum/Barz.h
index 7ec5c2cbb6d..cc6fa74998b 100644
--- a/src/Ethereum/Barz.h
+++ b/src/Ethereum/Barz.h
@@ -14,7 +14,7 @@
namespace TW::Barz {
std::string getCounterfactualAddress(const Proto::ContractAddressInput input);
-Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet);
+Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet, const uint32_t salt);
Data getFormattedSignature(const Data& signature, const Data challenge, const Data& authenticatorData, const std::string& clientDataJSON);
}
diff --git a/src/Ethereum/ContractCall.cpp b/src/Ethereum/ContractCall.cpp
index 1cd9e76fb85..f2850c21dc4 100644
--- a/src/Ethereum/ContractCall.cpp
+++ b/src/Ethereum/ContractCall.cpp
@@ -31,15 +31,15 @@ static void fill(ParamSet& paramSet, const string& type) {
}
}
-static vector getArrayValue(ParamSet& paramSet, const string& type, int idx) {
+static vector getArrayValue(const ParamSet& paramSet, const string& type, int idx) {
shared_ptr param;
paramSet.getParam(idx, param);
return ParamFactory::getArrayValue(param, type);
}
-static json buildInputs(ParamSet& paramSet, const json& registry); // forward
+static json buildInputs(const ParamSet& paramSet, const json& registry); // forward
-static json getTupleValue(ParamSet& paramSet, [[maybe_unused]] const string& type, int idx, const json& typeInfo) {
+static json getTupleValue(const ParamSet& paramSet, [[maybe_unused]] const string& type, int idx, const json& typeInfo) {
shared_ptr param;
paramSet.getParam(idx, param);
auto paramTuple = dynamic_pointer_cast(param);
@@ -49,13 +49,32 @@ static json getTupleValue(ParamSet& paramSet, [[maybe_unused]] const string& typ
return buildInputs(paramTuple->_params, typeInfo["components"]);
}
-static string getValue(ParamSet& paramSet, const string& type, int idx) {
+static vector getArrayValueTuple(const ParamSet& paramSet, int idx, const json& typeInfo) {
+ shared_ptr param;
+ paramSet.getParam(idx, param);
+
+ auto array = dynamic_pointer_cast(param);
+ if (!array) {
+ return {};
+ }
+
+ std::vector values;
+ for (const auto& tuple : array->getVal()) {
+ if (auto paramTuple = dynamic_pointer_cast(tuple); paramTuple) {
+ values.emplace_back(buildInputs(paramTuple->_params, typeInfo["components"]));
+ }
+ }
+
+ return values;
+}
+
+static string getValue(const ParamSet& paramSet, const string& type, int idx) {
shared_ptr param;
paramSet.getParam(idx, param);
return ParamFactory::getValue(param, type);
}
-static json buildInputs(ParamSet& paramSet, const json& registry) {
+static json buildInputs(const ParamSet& paramSet, const json& registry) {
auto inputs = json::array();
for (auto i = 0ul; i < registry.size(); i++) {
auto info = registry[i];
@@ -64,7 +83,9 @@ static json buildInputs(ParamSet& paramSet, const json& registry) {
{"name", info["name"]},
{"type", type}
};
- if (boost::algorithm::ends_with(type.get(), "[]")) {
+ if (type == "tuple[]") {
+ input["components"] = getArrayValueTuple(paramSet, static_cast(i), info);
+ } else if (boost::algorithm::ends_with(type.get(), "[]")) {
input["value"] = json(getArrayValue(paramSet, type, static_cast(i)));
} else if (type == "tuple") {
input["components"] = getTupleValue(paramSet, type, static_cast(i), info);
@@ -80,14 +101,18 @@ static json buildInputs(ParamSet& paramSet, const json& registry) {
void fillTuple(ParamSet& paramSet, const json& jsonSet); // forward
+void fillTupleArray(ParamSet& paramSet, const json& jsonSet); // forward
+
void decodeParamSet(ParamSet& paramSet, const json& jsonSet) {
for (auto& comp : jsonSet) {
if (comp["type"] == "tuple") {
fillTuple(paramSet, comp["components"]);
- } else {
+ } else if (comp["type"] == "tuple[]") {
+ fillTupleArray(paramSet, comp["components"]);
+ } else {
fill(paramSet, comp["type"]);
}
- }
+ }
}
void fillTuple(ParamSet& paramSet, const json& jsonSet) {
@@ -96,6 +121,14 @@ void fillTuple(ParamSet& paramSet, const json& jsonSet) {
paramSet.addParam(param);
}
+void fillTupleArray(ParamSet& paramSet, const json& jsonSet) {
+ std::shared_ptr tuple = make_shared();
+ decodeParamSet(tuple->_params, jsonSet);
+
+ auto tupleArray = make_shared(tuple);
+ paramSet.addParam(tupleArray);
+}
+
optional decodeCall(const Data& call, const json& abi) {
// check bytes length
if (call.size() <= 4) {
diff --git a/src/interface/TWBarz.cpp b/src/interface/TWBarz.cpp
index 955dd6103e9..b3261247494 100644
--- a/src/interface/TWBarz.cpp
+++ b/src/interface/TWBarz.cpp
@@ -21,12 +21,12 @@ TWString *_Nonnull TWBarzGetCounterfactualAddress(TWData *_Nonnull input) {
return TWStringCreateWithUTF8Bytes(TW::Barz::getCounterfactualAddress(inputProto).c_str());
}
-TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet) {
+TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet, uint32_t salt) {
const auto& factoryStr = *reinterpret_cast(factory);
const auto& publicKeyConverted = *reinterpret_cast(publicKey);
const auto& verificationFacetStr = *reinterpret_cast(verificationFacet);
- const auto initCode = TW::Barz::getInitCode(factoryStr, publicKeyConverted, verificationFacetStr);
+ const auto initCode = TW::Barz::getInitCode(factoryStr, publicKeyConverted, verificationFacetStr, salt);
return TWDataCreateWithData(&initCode);
}
diff --git a/src/interface/TWBitcoinFee.cpp b/src/interface/TWBitcoinFee.cpp
index 9836100bcf0..6250d46a580 100644
--- a/src/interface/TWBitcoinFee.cpp
+++ b/src/interface/TWBitcoinFee.cpp
@@ -6,14 +6,15 @@
#include
#include "Bitcoin/Transaction.h"
-#include "Data.h"
-uint64_t TWBitcoinFeeCalculateFee(TWData* _Nonnull data, uint64_t satVb) {
+TWString* _Nullable TWBitcoinFeeCalculateFee(TWData* _Nonnull data, TWString* _Nonnull satVb) {
auto* encoded = reinterpret_cast(data);
- auto fee = TW::Bitcoin::Transaction::calculateFee(*encoded, satVb);
+ const std::string& satVbStr = *reinterpret_cast(satVb);
+ uint64_t satVbInt = std::stoull(satVbStr);
+ auto fee = TW::Bitcoin::Transaction::calculateFee(*encoded, satVbInt);
if (!fee) {
- return 0;
+ return nullptr;
}
- return fee.value();
+ return TWStringCreateWithUTF8Bytes(std::to_string(*fee).c_str());
}
diff --git a/src/proto/Aptos.proto b/src/proto/Aptos.proto
index 9d28e3c58aa..6f124b47423 100644
--- a/src/proto/Aptos.proto
+++ b/src/proto/Aptos.proto
@@ -27,7 +27,7 @@ message StructTag {
string name = 3;
}
-// Necessary fields to process a TokenTransferMessage
+// Necessary fields to process a `0x1::coin::transfer` function.
message TokenTransferMessage {
// Destination Account address (string)
string to = 1;
@@ -37,6 +37,17 @@ message TokenTransferMessage {
StructTag function = 3;
}
+// Necessary fields to process a `0x1::aptos_account::transfer_coins` function.
+// Can be used to transfer tokens with registering the recipient account if needed.
+message TokenTransferCoinsMessage {
+ // Destination Account address (string)
+ string to = 1;
+ // Amount to be transferred (uint64)
+ uint64 amount = 2;
+ // token function to call, e.g BTC: 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC
+ StructTag function = 3;
+}
+
// Necessary fields to process a ManagedTokensRegisterMessage
message ManagedTokensRegisterMessage {
// token function to register, e.g BTC: 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC
@@ -153,6 +164,7 @@ message SigningInput {
NftMessage nft_message = 12;
ManagedTokensRegisterMessage register_token = 13;
LiquidStaking liquid_staking_message = 14;
+ TokenTransferCoinsMessage token_transfer_coins = 15;
}
}
diff --git a/src/proto/Barz.proto b/src/proto/Barz.proto
index 0165295481b..20853f04ad4 100644
--- a/src/proto/Barz.proto
+++ b/src/proto/Barz.proto
@@ -26,4 +26,7 @@ message ContractAddressInput {
string bytecode = 7;
// PublicKey of the wallet
string public_key = 8;
+
+ // Salt is used to derive multiple account from the same public key
+ uint32 salt = 9;
}
diff --git a/swift/Tests/BarzTests.swift b/swift/Tests/BarzTests.swift
index b2f81dbab60..d86ae0b1aba 100644
--- a/swift/Tests/BarzTests.swift
+++ b/swift/Tests/BarzTests.swift
@@ -15,10 +15,19 @@ class BarzTests: XCTestCase {
let publicKeyData = Data(hexString: "0x04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")!
let publicKey = PublicKey(data: publicKeyData, type: .nist256p1Extended)!
let verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
- let result = Barz.getInitCode(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet)
+ let result = Barz.getInitCode(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet, salt: 0)
XCTAssertEqual(result.hexString, "3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000")
}
+ func testInitCodeNoneZeroSalt() {
+ let factoryAddress = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800"
+ let publicKeyData = Data(hexString: "0x04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")!
+ let publicKey = PublicKey(data: publicKeyData, type: .nist256p1Extended)!
+ let verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
+ let result = Barz.getInitCode(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet, salt: 1)
+ XCTAssertEqual(result.hexString, "3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000")
+ }
+
func testCounterfactualAddress() {
let input = BarzContractAddressInput.with {
$0.factory = "0x2c97f4a366Dd5D91178ec9E36c5C1fcA393A538C"
@@ -29,11 +38,28 @@ class BarzTests: XCTestCase {
$0.defaultFallback = "0x22eB0720d9Fc4bC90BB812B309e939880B71c20d"
$0.bytecode = bytecode
$0.publicKey = "0xB5547FBdC56DCE45e1B8ef75569916D438e09c46"
+ $0.salt = 0
}
XCTAssertEqual(Barz.getCounterfactualAddress(input: try! input.serializedData()), "0x77F62bb3E43190253D4E198199356CD2b25063cA");
}
+ func testCounterfactualAddressNonZeroSalt() {
+ let input = BarzContractAddressInput.with {
+ $0.factory = "0x96C489979E39F877BDb8637b75A25C1a5B2DE14C"
+ $0.accountFacet = "0xF6F5e5fC74905e65e3FF53c6BacEba8535dd14d1"
+ $0.verificationFacet = "0xaB84813cbf26Fd951CB3d7E33Dccb8995027e490"
+ $0.entryPoint = entryPoint
+ $0.facetRegistry = "0x9a95d201BB8F559771784D12c01F8084278c65E5"
+ $0.defaultFallback = "0x522cDc7558b5f798dF5D61AB09B6D95Ebd342EF9"
+ $0.bytecode = "0x60806040526040516104c83803806104c883398101604081905261002291610163565b6000858585858560405160240161003d959493929190610264565b60408051601f198184030181529181526020820180516001600160e01b0316634a93641760e01b1790525190915060009081906001600160a01b038a16906100869085906102c3565b600060405180830381855af49150503d80600081146100c1576040519150601f19603f3d011682016040523d82523d6000602084013e6100c6565b606091505b50915091508115806100e157506100dc816102df565b600114155b156100ff57604051636ff35f8960e01b815260040160405180910390fd5b505050505050505050610306565b80516001600160a01b038116811461012457600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561015a578181015183820152602001610142565b50506000910152565b60008060008060008060c0878903121561017c57600080fd5b6101858761010d565b95506101936020880161010d565b94506101a16040880161010d565b93506101af6060880161010d565b92506101bd6080880161010d565b60a08801519092506001600160401b03808211156101da57600080fd5b818901915089601f8301126101ee57600080fd5b81518181111561020057610200610129565b604051601f8201601f19908116603f0116810190838211818310171561022857610228610129565b816040528281528c602084870101111561024157600080fd5b61025283602083016020880161013f565b80955050505050509295509295509295565b600060018060a01b0380881683528087166020840152808616604084015280851660608401525060a0608083015282518060a08401526102ab8160c085016020870161013f565b601f01601f19169190910160c0019695505050505050565b600082516102d581846020870161013f565b9190910192915050565b80516020808301519190811015610300576000198160200360031b1b821691505b50919050565b6101b3806103156000396000f3fe60806040523661000b57005b600080356001600160e01b03191681527f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f6020819052604090912054819060601c806100cf576004838101546040516366ffd66360e11b81526000356001600160e01b031916928101929092526001600160a01b03169063cdffacc690602401602060405180830381865afa1580156100a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100cc919061014d565b90505b6001600160a01b0381166101295760405162461bcd60e51b815260206004820152601d60248201527f4261727a3a2046756e6374696f6e20646f6573206e6f74206578697374000000604482015260640160405180910390fd5b3660008037600080366000845af43d6000803e808015610148573d6000f35b3d6000fd5b60006020828403121561015f57600080fd5b81516001600160a01b038116811461017657600080fd5b939250505056fea2646970667358221220d35db061bb6ecdb7688c3674af669ce44d527cae4ded59214d06722d73da62be64736f6c63430008120033"
+ $0.publicKey = "0xB5547FBdC56DCE45e1B8ef75569916D438e09c46"
+ $0.salt = 123456
+ }
+
+ XCTAssertEqual(Barz.getCounterfactualAddress(input: try! input.serializedData()), "0xB91aaa96B138A1B1D94c9df4628187132c5F2bf1");
+ }
+
func testFormatSignature() {
let signature = Data(hexString: "0x3044022012d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf0220256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca276")!
let challenge = Data(hexString: "0xcf267a78c5adaf96f341a696eb576824284c572f3e61be619694d539db1925f9")!
@@ -96,7 +122,8 @@ class BarzTests: XCTestCase {
$0.initCode = Barz.getInitCode(
factory: factory,
publicKey: publicKey,
- verificationFacet: "0x5034534Efe9902779eD6eA6983F435c00f3bc510"
+ verificationFacet: "0x5034534Efe9902779eD6eA6983F435c00f3bc510",
+ salt: 0
)
}
diff --git a/swift/Tests/Blockchains/BitcoinTests.swift b/swift/Tests/Blockchains/BitcoinTests.swift
index 2155db798b2..95dc60c4fcd 100644
--- a/swift/Tests/Blockchains/BitcoinTests.swift
+++ b/swift/Tests/Blockchains/BitcoinTests.swift
@@ -473,17 +473,19 @@ class BitcoinTransactionSignerTests: XCTestCase {
}
func testBitcoinP2pkhCalculateFee() throws {
- let satVb: UInt64 = 10
+ let satVb = "10"
let tx = Data(hexString: "02000000017be4e642bb278018ab12277de9427773ad1c5f5b1d164a157e0d99aa48dc1c1e000000006a473044022078eda020d4b86fcb3af78ef919912e6d79b81164dbbb0b0b96da6ac58a2de4b102201a5fd8d48734d5a02371c4b5ee551a69dca3842edbf577d863cf8ae9fdbbd4590121036666dd712e05a487916384bfcd5973eb53e8038eccbbf97f7eed775b87389536ffffffff01c0aff629010000001976a9145eaaa4f458f9158f86afcba08dd7448d27045e3d88ac00000000")!
- let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)
- XCTAssertEqual(fee, 191 * satVb)
+ let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)!
+ let feeInt = UInt64(fee)!
+ XCTAssertEqual(feeInt, 191 * 10)
}
func testBitcoinP2wpkhCalculateFee() throws {
- let satVb: UInt64 = 12
+ let satVb = "12"
let tx = Data(hexString: "020000000111b9f62923af73e297abb69f749e7a1aa2735fbdfd32ac5f6aa89e5c96841c18000000006b483045022100df9ed0b662b759e68b89a42e7144cddf787782a7129d4df05642dd825930e6e6022051a08f577f11cc7390684bbad2951a6374072253ffcf2468d14035ed0d8cd6490121028d7dce6d72fb8f7af9566616c6436349c67ad379f2404dd66fe7085fe0fba28fffffffff01c0aff629010000001600140d0e1cec6c2babe8badde5e9b3dea667da90036d00000000")!
- let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)
- XCTAssertEqual(fee, 189 * satVb)
+ let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)!
+ let feeInt = UInt64(fee)!
+ XCTAssertEqual(feeInt, 189 * 12)
}
// Metadata can be observed live on:
@@ -493,10 +495,11 @@ class BitcoinTransactionSignerTests: XCTestCase {
// Size 235 Bytes
// Weight 610
func testBitcoinBrc20TransferCommitCalculateFee() throws {
- let satVb: UInt64 = 19
+ let satVb = "19"
let tx = Data(hexString: "02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000")!
- let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)
- XCTAssertEqual(fee, 153 * satVb) // 153 = ceil(610/4)
+ let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)!
+ let feeInt = UInt64(fee);
+ XCTAssertEqual(feeInt, 153 * 19) // 153 = ceil(610/4)
}
}
diff --git a/swift/Tests/CoinAddressDerivationTests.swift b/swift/Tests/CoinAddressDerivationTests.swift
index c5f39c9d51f..ed6254e2a8f 100644
--- a/swift/Tests/CoinAddressDerivationTests.swift
+++ b/swift/Tests/CoinAddressDerivationTests.swift
@@ -108,7 +108,8 @@ class CoinAddressDerivationTests: XCTestCase {
.confluxeSpace,
.opBNBtestnet,
.acalaEVM,
- .neon:
+ .neon,
+ .base:
let expectedResult = "0x8f348F300873Fd5DA36950B2aC75a26584584feE"
assertCoinDerivation(coin, expectedResult, derivedAddress, address)
case .ronin:
diff --git a/tests/chains/Aptos/SignerTests.cpp b/tests/chains/Aptos/SignerTests.cpp
index b12e6de891f..65c0bc87089 100644
--- a/tests/chains/Aptos/SignerTests.cpp
+++ b/tests/chains/Aptos/SignerTests.cpp
@@ -681,4 +681,50 @@ TEST(AptosSigner, TokenTxSign) {
assertJSONEqual(expectedJson, parsedJson);
}
+TEST(AptosSigner, TokenTransferCoins) {
+ // Successfully broadcasted https://explorer.aptoslabs.com/txn/0x197d40ea12e2bfc65a0a913b9f4ca3b0b0208fe0c1514d3d55cef3d5bcf25211?network=mainnet
+ Proto::SigningInput input;
+ input.set_sender("0x1869b853768f0ba935d67f837a66b172dd39a60ca2315f8d4e0e669bbd35cf25");
+ input.set_sequence_number(2);
+ auto& tf = *input.mutable_token_transfer_coins();
+ tf.set_to("0xb7c7d12080209e9dc14498c80200706e760363fb31782247e82cf57d1d6e5d6c");
+ tf.set_amount(10000);
+ tf.mutable_function()->set_account_address("0xe9c192ff55cffab3963c695cff6dbf9dad6aff2bb5ac19a6415cad26a81860d9");
+ tf.mutable_function()->set_module("mee_coin");
+ tf.mutable_function()->set_name("MeeCoin");
+ input.set_max_gas_amount(2000);
+ input.set_gas_unit_price(100);
+ input.set_expiration_timestamp_secs(3664390082);
+ input.set_chain_id(1);
+ auto privateKey = PrivateKey(parse_hex("e7f56c77189e03699a75d8ec5c090e41f3d9d4783bc49c33df8a93d915e10de8"));
+ input.set_private_key(privateKey.bytes.data(), privateKey.bytes.size());
+ auto result = Signer::sign(input);
+
+ ASSERT_EQ(hex(result.raw_txn()), "1869b853768f0ba935d67f837a66b172dd39a60ca2315f8d4e0e669bbd35cf2502000000000000000200000000000000000000000000000000000000000000000000000000000000010d6170746f735f6163636f756e740e7472616e736665725f636f696e730107e9c192ff55cffab3963c695cff6dbf9dad6aff2bb5ac19a6415cad26a81860d9086d65655f636f696e074d6565436f696e000220b7c7d12080209e9dc14498c80200706e760363fb31782247e82cf57d1d6e5d6c081027000000000000d0070000000000006400000000000000c2276ada0000000001");
+ ASSERT_EQ(hex(result.authenticator().signature()), "30ebd7e95cb464677f411868e2cbfcb22bc01cc63cded36c459dff45e6d2f1354ae4e090e7dfbb509851c0368b343e0e5ecaf6b08e7c1b94c186530b0f7dee0d");
+ ASSERT_EQ(hex(result.encoded()), "1869b853768f0ba935d67f837a66b172dd39a60ca2315f8d4e0e669bbd35cf2502000000000000000200000000000000000000000000000000000000000000000000000000000000010d6170746f735f6163636f756e740e7472616e736665725f636f696e730107e9c192ff55cffab3963c695cff6dbf9dad6aff2bb5ac19a6415cad26a81860d9086d65655f636f696e074d6565436f696e000220b7c7d12080209e9dc14498c80200706e760363fb31782247e82cf57d1d6e5d6c081027000000000000d0070000000000006400000000000000c2276ada0000000001002062e7a6a486553b56a53e89dfae3f780693e537e5b0a7ed33290780e581ca83694030ebd7e95cb464677f411868e2cbfcb22bc01cc63cded36c459dff45e6d2f1354ae4e090e7dfbb509851c0368b343e0e5ecaf6b08e7c1b94c186530b0f7dee0d");
+ nlohmann::json expectedJson = R"(
+ {
+ "expiration_timestamp_secs": "3664390082",
+ "gas_unit_price": "100",
+ "max_gas_amount": "2000",
+ "payload": {
+ "arguments": ["0xb7c7d12080209e9dc14498c80200706e760363fb31782247e82cf57d1d6e5d6c","10000"],
+ "function": "0x1::aptos_account::transfer_coins",
+ "type": "entry_function_payload",
+ "type_arguments": ["0xe9c192ff55cffab3963c695cff6dbf9dad6aff2bb5ac19a6415cad26a81860d9::mee_coin::MeeCoin"]
+ },
+ "sender": "0x1869b853768f0ba935d67f837a66b172dd39a60ca2315f8d4e0e669bbd35cf25",
+ "sequence_number": "2",
+ "signature": {
+ "public_key": "0x62e7a6a486553b56a53e89dfae3f780693e537e5b0a7ed33290780e581ca8369",
+ "signature": "0x30ebd7e95cb464677f411868e2cbfcb22bc01cc63cded36c459dff45e6d2f1354ae4e090e7dfbb509851c0368b343e0e5ecaf6b08e7c1b94c186530b0f7dee0d",
+ "type": "ed25519_signature"
+ }
+ }
+ )"_json;
+ nlohmann::json parsedJson = nlohmann::json::parse(result.json());
+ assertJSONEqual(expectedJson, parsedJson);
+}
+
} // namespace TW::Aptos::tests
diff --git a/tests/chains/Base/TWCoinTypeTests.cpp b/tests/chains/Base/TWCoinTypeTests.cpp
new file mode 100644
index 00000000000..a07285626d2
--- /dev/null
+++ b/tests/chains/Base/TWCoinTypeTests.cpp
@@ -0,0 +1,37 @@
+// Copyright © 2017-2023 Trust Wallet.
+//
+// This file is part of Trust. The full Trust copyright notice, including
+// terms governing use, modification, and redistribution, is contained in the
+// file LICENSE at the root of the source code distribution tree.
+//
+// This is a GENERATED FILE, changes made here MAY BE LOST.
+// Generated one-time (codegen/bin/cointests)
+//
+
+#include "TestUtilities.h"
+#include
+#include
+
+
+TEST(TWBaseCoinType, TWCoinType) {
+ const auto coin = TWCoinTypeBase;
+ const auto symbol = WRAPS(TWCoinTypeConfigurationGetSymbol(coin));
+ const auto id = WRAPS(TWCoinTypeConfigurationGetID(coin));
+ const auto name = WRAPS(TWCoinTypeConfigurationGetName(coin));
+ const auto chainId = WRAPS(TWCoinTypeChainId(coin));
+ const auto txId = WRAPS(TWStringCreateWithUTF8Bytes("0x4acb15506b7696a2dfac4258f3f86392b4b2b717a3f316a8aa78509b2c3b6ab4"));
+ const auto txUrl = WRAPS(TWCoinTypeConfigurationGetTransactionURL(coin, txId.get()));
+ const auto accId = WRAPS(TWStringCreateWithUTF8Bytes("0xb8ff877ed78ba520ece21b1de7843a8a57ca47cb"));
+ const auto accUrl = WRAPS(TWCoinTypeConfigurationGetAccountURL(coin, accId.get()));
+
+ assertStringsEqual(id, "base");
+ assertStringsEqual(name, "Base");
+ assertStringsEqual(symbol, "ETH");
+ ASSERT_EQ(TWCoinTypeConfigurationGetDecimals(coin), 18);
+ ASSERT_EQ(TWCoinTypeBlockchain(coin), TWBlockchainEthereum);
+ ASSERT_EQ(TWCoinTypeP2shPrefix(coin), 0x0);
+ ASSERT_EQ(TWCoinTypeStaticPrefix(coin), 0x0);
+ assertStringsEqual(chainId, "8453");
+ assertStringsEqual(txUrl, "https://basescan.org/tx/0x4acb15506b7696a2dfac4258f3f86392b4b2b717a3f316a8aa78509b2c3b6ab4");
+ assertStringsEqual(accUrl, "https://basescan.org/address/0xb8ff877ed78ba520ece21b1de7843a8a57ca47cb");
+}
diff --git a/tests/chains/Bitcoin/TWBitcoinFeeTests.cpp b/tests/chains/Bitcoin/TWBitcoinFeeTests.cpp
index 0692760478f..87fa9b584ac 100644
--- a/tests/chains/Bitcoin/TWBitcoinFeeTests.cpp
+++ b/tests/chains/Bitcoin/TWBitcoinFeeTests.cpp
@@ -11,17 +11,17 @@
namespace TW::Bitcoin {
TEST(TWBitcoinFee, P2pkhFee) {
- auto satVb = 10;
+ const auto satVb = STRING("10");
auto data = DATA("02000000017be4e642bb278018ab12277de9427773ad1c5f5b1d164a157e0d99aa48dc1c1e000000006a473044022078eda020d4b86fcb3af78ef919912e6d79b81164dbbb0b0b96da6ac58a2de4b102201a5fd8d48734d5a02371c4b5ee551a69dca3842edbf577d863cf8ae9fdbbd4590121036666dd712e05a487916384bfcd5973eb53e8038eccbbf97f7eed775b87389536ffffffff01c0aff629010000001976a9145eaaa4f458f9158f86afcba08dd7448d27045e3d88ac00000000");
- auto fee = TWBitcoinFeeCalculateFee(data.get(), satVb);
- ASSERT_EQ(fee, 191 * satVb);
+ const auto fee = WRAPS(TWBitcoinFeeCalculateFee(data.get(), satVb.get()));
+ assertStringsEqual(fee, std::to_string(191UL * 10).c_str());
}
TEST(TWBitcoinFee, P2wpkhFee) {
- auto satVb = 12;
+ const auto satVb = STRING("12");
auto data = DATA("020000000111b9f62923af73e297abb69f749e7a1aa2735fbdfd32ac5f6aa89e5c96841c18000000006b483045022100df9ed0b662b759e68b89a42e7144cddf787782a7129d4df05642dd825930e6e6022051a08f577f11cc7390684bbad2951a6374072253ffcf2468d14035ed0d8cd6490121028d7dce6d72fb8f7af9566616c6436349c67ad379f2404dd66fe7085fe0fba28fffffffff01c0aff629010000001600140d0e1cec6c2babe8badde5e9b3dea667da90036d00000000");
- auto fee = TWBitcoinFeeCalculateFee(data.get(), satVb);
- ASSERT_EQ(fee, 189 * satVb);
+ const auto fee = WRAPS(TWBitcoinFeeCalculateFee(data.get(), satVb.get()));
+ assertStringsEqual(fee, std::to_string(189UL * 12).c_str());
}
// Metadata can be observed live on:
@@ -31,10 +31,10 @@ TEST(TWBitcoinFee, P2wpkhFee) {
// Size 235 Bytes
// Weight 610
TEST(TWBitcoinFee, BRC20TransferCommitFee) {
- auto satVb = 19;
+ const auto satVb = STRING("19");
auto data = DATA("02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000");
- auto fee = TWBitcoinFeeCalculateFee(data.get(), satVb);
- ASSERT_EQ(fee, 153 * satVb); // 153 = ceil(610/4)
+ const auto fee = WRAPS(TWBitcoinFeeCalculateFee(data.get(), satVb.get()));
+ assertStringsEqual(fee, std::to_string(153UL * 19).c_str()); // 153 = ceil(610/4)
}
} // namespace TW::Bitcoin
diff --git a/tests/chains/Ethereum/AbiTests.cpp b/tests/chains/Ethereum/AbiTests.cpp
index c1eceb2acf3..14e9e971fdb 100644
--- a/tests/chains/Ethereum/AbiTests.cpp
+++ b/tests/chains/Ethereum/AbiTests.cpp
@@ -856,7 +856,8 @@ TEST(EthereumAbi, DecodeArrayOfByteArray) {
bool res = param.decode(encoded, offset);
EXPECT_TRUE(res);
EXPECT_EQ(2ul, param.getCount());
- EXPECT_EQ(7 * 32ul, offset);
+ // `size_of(array.len())` + `size_of(byte_array[0].len())` + `size_of(byte_array[1].len())
+ EXPECT_EQ(3 * 32ul, offset);
EXPECT_EQ(2ul, param.getVal().size());
}
@@ -986,7 +987,8 @@ TEST(EthereumAbi, DecodeParamsMixed) {
EXPECT_EQ(3, (std::dynamic_pointer_cast((std::dynamic_pointer_cast(p.getParam(1)))->getParam(2)))->getVal());
EXPECT_EQ(true, (std::dynamic_pointer_cast(p.getParam(2)))->getVal());
EXPECT_EQ("Hello", (std::dynamic_pointer_cast(p.getParam(3)))->getVal());
- EXPECT_EQ(13 * 32ul, offset);
+ // Offset of `ParamUInt256`, `ParamBool` static elements and sizes of `ParamArray`, `ParamBool`, `ParamByteArray`.
+ EXPECT_EQ(5 * 32ul, offset);
}
///// Function encode & decode
@@ -1113,7 +1115,8 @@ TEST(EthereumAbi, DecodeFunctionOutputCase2) {
size_t offset = 0;
bool res = func.decodeOutput(encoded, offset);
EXPECT_TRUE(res);
- EXPECT_EQ(128ul, offset);
+ // The offset should only be shifted by the size of the array.
+ EXPECT_EQ(32ul, offset);
// new output values
std::shared_ptr param;
@@ -1185,7 +1188,8 @@ TEST(EthereumAbi, DecodeFunctionInputWithDynamicArgumentsCase1) {
EXPECT_EQ(3ul, (std::dynamic_pointer_cast(param))->getCount());
EXPECT_EQ(uint256_t(1), (std::dynamic_pointer_cast((std::dynamic_pointer_cast(param))->getVal()[0]))->getVal());
EXPECT_EQ(uint256_t(3), (std::dynamic_pointer_cast((std::dynamic_pointer_cast(param))->getVal()[2]))->getVal());
- EXPECT_EQ(4 + 9 * 32ul, offset);
+ // Offset of `ParamBool` static element and sizes of `ParamByteArray`, `ParamArray` arrays.
+ EXPECT_EQ(4 + 3 * 32ul, offset);
}
TEST(EthereumAbi, DecodeFunctionInputWithDynamicArgumentsCase2) {
@@ -1228,7 +1232,8 @@ TEST(EthereumAbi, DecodeFunctionInputWithDynamicArgumentsCase2) {
EXPECT_EQ("31323334353637383930", hex((std::dynamic_pointer_cast(param))->getVal()));
EXPECT_TRUE(func.getInParam(3, param));
EXPECT_EQ(std::string("Hello, world!"), (std::dynamic_pointer_cast(param))->getVal());
- EXPECT_EQ(4 + 9 * 32ul, offset);
+ // Offset of `ParamUInt256` static element and sizes of `ParamArray`, `ParamByteArrayFix`, `ParamString` dynamic arrays.
+ EXPECT_EQ(4 + 4 * 32ul, offset);
}
TEST(EthereumAbi, DecodeFunctionContractMulticall) {
@@ -1271,7 +1276,8 @@ TEST(EthereumAbi, DecodeFunctionContractMulticall) {
size_t offset = 0;
bool res = func.decodeInput(encoded, offset);
EXPECT_TRUE(res);
- EXPECT_EQ(4 + 29 * 32ul, offset);
+ // The offset should only be shifted by the size of the array.
+ EXPECT_EQ(4 + 32ul, offset);
}
TEST(EthereumAbi, ParamFactoryMake) {
diff --git a/tests/chains/Ethereum/BarzTests.cpp b/tests/chains/Ethereum/BarzTests.cpp
index 7c6a5763d4d..842da520541 100644
--- a/tests/chains/Ethereum/BarzTests.cpp
+++ b/tests/chains/Ethereum/BarzTests.cpp
@@ -20,26 +20,47 @@ namespace TW::Barz::tests {
// https://testnet.bscscan.com/tx/0x6c6e1fe81c722c0abce1856b9b4e078ab2cad06d51f2d1b04945e5ba2286d1b4
TEST(Barz, GetInitCode) {
- // C++
const PublicKey& publicKey = PublicKey(parse_hex("0x04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02"), TWPublicKeyTypeNIST256p1Extended);
+ // C++
{
const std::string& factoryAddress = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800";
const std::string& verificationFacetAddress = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf";
+ const auto salt = 0;
- const auto& initCode = Barz::getInitCode(factoryAddress, publicKey, verificationFacetAddress);
+ const auto& initCode = Barz::getInitCode(factoryAddress, publicKey, verificationFacetAddress, salt);
ASSERT_EQ(hexEncoded(initCode), "0x3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000");
}
+ {
+ const std::string& factoryAddress = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800";
+ const std::string& verificationFacetAddress = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf";
+ const auto salt = 1;
+
+ const auto& initCode = Barz::getInitCode(factoryAddress, publicKey, verificationFacetAddress, salt);
+ ASSERT_EQ(hexEncoded(initCode), "0x3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000");
+ }
+
// C
{
const auto factoryAddress = STRING("0x3fC708630d85A3B5ec217E53100eC2b735d4f800");
const auto verificationFacetAddress = STRING("0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf");
+ const auto salt = 0;
- const auto& initCodeData = TWBarzGetInitCode(factoryAddress.get(), WRAP(TWPublicKey, new TWPublicKey{ TW::PublicKey(publicKey) }).get(), verificationFacetAddress.get());
+ const auto& initCodeData = TWBarzGetInitCode(factoryAddress.get(), WRAP(TWPublicKey, new TWPublicKey{ TW::PublicKey(publicKey) }).get(), verificationFacetAddress.get(), salt);
const auto& initCode = hexEncoded(*reinterpret_cast(WRAPD(initCodeData).get()));
EXPECT_EQ(initCode, "0x3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000");
}
+
+ {
+ const auto factoryAddress = STRING("0x3fC708630d85A3B5ec217E53100eC2b735d4f800");
+ const auto verificationFacetAddress = STRING("0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf");
+ const auto salt = 1;
+
+ const auto& initCodeData = TWBarzGetInitCode(factoryAddress.get(), WRAP(TWPublicKey, new TWPublicKey{ TW::PublicKey(publicKey) }).get(), verificationFacetAddress.get(), salt);
+ const auto& initCode = hexEncoded(*reinterpret_cast(WRAPD(initCodeData).get()));
+ EXPECT_EQ(initCode, "0x3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000");
+ }
}
TEST(Barz, GetCounterfactualAddress) {
@@ -52,6 +73,7 @@ TEST(Barz, GetCounterfactualAddress) {
input.set_default_fallback("0x22eB0720d9Fc4bC90BB812B309e939880B71c20d");
input.set_bytecode("0x608060405260405162003cc638038062003cc68339818101604052810190620000299190620019ad565b60008673ffffffffffffffffffffffffffffffffffffffff16633253960f6040518163ffffffff1660e01b81526004016020604051808303816000875af115801562000079573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009f919062001aec565b9050600060e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603620000fe576040517f5a5b4d3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600267ffffffffffffffff8111156200011e576200011d6200196b565b5b6040519080825280602002602001820160405280156200015b57816020015b62000147620018ff565b8152602001906001900390816200013d5790505b5090506000600167ffffffffffffffff8111156200017e576200017d6200196b565b5b604051908082528060200260200182016040528015620001ad5781602001602082028036833780820191505090505b5090506000600167ffffffffffffffff811115620001d057620001cf6200196b565b5b604051908082528060200260200182016040528015620001ff5781602001602082028036833780820191505090505b509050631f931c1c60e01b8260008151811062000221576200022062001b21565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505060405180606001604052808d73ffffffffffffffffffffffffffffffffffffffff16815260200160006002811115620002ab57620002aa62001b37565b5b81526020018381525083600081518110620002cb57620002ca62001b21565b5b60200260200101819052508381600081518110620002ee57620002ed62001b21565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505060405180606001604052808b73ffffffffffffffffffffffffffffffffffffffff1681526020016000600281111562000378576200037762001b37565b5b8152602001828152508360018151811062000398576200039762001b21565b5b6020026020010181905250620003b9846200047e60201b620001671760201c565b6200046c838c8b8e8e8d8d8d8d604051602401620003de979695949392919062001b8c565b6040516020818303038152906040527f95a21aec000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050620004b060201b620001911760201c565b5050505050505050505050506200211f565b806200048f6200073460201b60201c565b60010160016101000a81548163ffffffff021916908360e01c021790555050565b60005b8351811015620006df576000848281518110620004d557620004d462001b21565b5b602002602001015160200151905060006002811115620004fa57620004f962001b37565b5b81600281111562000510576200050f62001b37565b5b0362000570576200056a85838151811062000530576200052f62001b21565b5b60200260200101516000015186848151811062000552576200055162001b21565b5b6020026020010151604001516200073960201b60201c565b620006c8565b6001600281111562000587576200058662001b37565b5b8160028111156200059d576200059c62001b37565b5b03620005fd57620005f7858381518110620005bd57620005bc62001b21565b5b602002602001015160000151868481518110620005df57620005de62001b21565b5b602002602001015160400151620009db60201b60201c565b620006c7565b60028081111562000613576200061262001b37565b5b81600281111562000629576200062862001b37565b5b0362000689576200068385838151811062000649576200064862001b21565b5b6020026020010151600001518684815181106200066b576200066a62001b21565b5b60200260200101516040015162000c8f60201b60201c565b620006c6565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620006bd9062001be7565b60405180910390fd5b5b5b508080620006d69062001c61565b915050620004b3565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb673838383604051620007159392919062001c82565b60405180910390a16200072f828262000e3760201b60201c565b505050565b600090565b600081511162000780576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007779062001d97565b60405180910390fd5b60006200079262000f6b60201b60201c565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000806576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007fd9062001dfb565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff16036200087c576200087b828562000f9860201b60201c565b5b60005b8351811015620009d4576000848281518110620008a157620008a062001b21565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161462000998576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200098f9062001e5f565b60405180910390fd5b620009ac8583868a6200107c60201b60201c565b8380620009b99062001ec3565b94505050508080620009cb9062001c61565b9150506200087f565b5050505050565b600081511162000a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000a199062001d97565b60405180910390fd5b600062000a3462000f6b60201b60201c565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000aa8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000a9f9062001dfb565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff160362000b1e5762000b1d828562000f9860201b60201c565b5b60005b835181101562000c8857600084828151811062000b435762000b4262001b21565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000c39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000c309062001eef565b60405180910390fd5b62000c4c8582846200122960201b60201c565b62000c608583868a6200107c60201b60201c565b838062000c6d9062001ec3565b9450505050808062000c7f9062001c61565b91505062000b21565b5050505050565b600081511162000cd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000ccd9062001d97565b60405180910390fd5b600062000ce862000f6b60201b60201c565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161462000d5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000d539062001f53565b60405180910390fd5b60005b825181101562000e3157600083828151811062000d815762000d8062001b21565b5b602002602001015190506000836000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905062000e198482846200122960201b60201c565b5050808062000e289062001c61565b91505062000d5f565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16031562000f675762000e988260405180606001604052806028815260200162003c7a60289139620018aa60201b60201c565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405162000ec2919062001fb7565b600060405180830381855af49150503d806000811462000eff576040519150601f19603f3d011682016040523d82523d6000602084013e62000f04565b606091505b50915091508162000f645760008151111562000f235780518082602001fd5b83836040517f192105d700000000000000000000000000000000000000000000000000000000815260040162000f5b92919062001fd7565b60405180910390fd5b50505b5050565b6000807f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f90508091505090565b62000fc38160405180606001604052806024815260200162003ca260249139620018aa60201b60201c565b81600201805490508260010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555081600201819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b81846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508360010160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018390806001815401808255809150506001900390600052602060002090600891828204019190066004029091909190916101000a81548163ffffffff021916908360e01c021790555080846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036200129b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620012929062002003565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036200130c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620013039062002067565b60405180910390fd5b6000836000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff169050600060018560010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000180549050620013e59190620020cb565b9050808214620015805760008560010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000182815481106200144a576200144962001b21565b5b90600052602060002090600891828204019190066004029054906101000a900460e01b9050808660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018481548110620014c957620014c862001b21565b5b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555082866000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505b8460010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001805480620015d757620015d6620020ec565b5b60019003818190600052602060002090600891828204019190066004026101000a81549063ffffffff02191690559055846000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a8154906bffffffffffffffffffffffff0219169055505060008103620018a357600060018660020180549050620016c49190620020cb565b905060008660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015490508181146200180c57600087600201838154811062001732576200173162001b21565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508088600201838154811062001779576200177862001b21565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818860010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505b86600201805480620018235762001822620020ec565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000905550505b5050505050565b6000823b9050600081118290620018f9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620018f0919062002102565b60405180910390fd5b50505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600060028111156200193e576200193d62001b37565b5b8152602001606081525090565b60008151905060018060a01b03811681146200196657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620019a157808201518184015260208101905062001984565b50600083830152505050565b600080600080600080600080610100898b031215620019cb57600080fd5b620019d6896200194b565b9750620019e660208a016200194b565b9650620019f660408a016200194b565b955062001a0660608a016200194b565b945062001a1660808a016200194b565b935062001a2660a08a016200194b565b925062001a3660c08a016200194b565b915060e089015160018060401b038082111562001a5257600080fd5b818b0191508b601f83011262001a6757600080fd5b81518181111562001a7d5762001a7c6200196b565b5b601f1960405181603f83601f860116011681019150808210848311171562001aaa5762001aa96200196b565b5b816040528281528e602084870101111562001ac457600080fd5b62001ad783602083016020880162001981565b80955050505050509295985092959890939650565b60006020828403121562001aff57600080fd5b815163ffffffff60e01b8116811462001b1757600080fd5b8091505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60018060a01b03811682525050565b6000815180845262001b7681602086016020860162001981565b6020601f19601f83011685010191505092915050565b600060018060a01b03808a168352808916602084015280881660408401528087166060840152808616608084015280851660a08401525060e060c083015262001bd960e083018462001b5c565b905098975050505050505050565b60208152602760208201527f4c69624469616d6f6e644375743a20496e636f7272656374204661636574437560408201527f74416374696f6e0000000000000000000000000000000000000000000000000060608201526000608082019050919050565b634e487b7160e01b600052601160045260246000fd5b60008019820362001c775762001c7662001c4b565b5b600182019050919050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b8481101562001d6357607f198a8503018652815188850160018060a01b038251168652848201516003811062001cf157634e487b7160e01b600052602160045260246000fd5b80868801525060408083015192508a81880152508082518083528a880191508684019350600092505b8083101562001d465763ffffffff60e01b84511682528682019150868401935060018301925062001d1a565b508096505050508282019150828601955060018101905062001cab565b505062001d738189018b62001b4d565b50868103604088015262001d88818962001b5c565b95505050505050949350505050565b60208152602b60208201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201527f6163657420746f2063757400000000000000000000000000000000000000000060608201526000608082019050919050565b60208152602c60208201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201527f652061646472657373283029000000000000000000000000000000000000000060608201526000608082019050919050565b60208152603560208201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60408201527f6e207468617420616c726561647920657869737473000000000000000000000060608201526000608082019050919050565b600060018060601b0380831681810362001ee25762001ee162001c4b565b5b6001810192505050919050565b60208152603860208201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60408201527f6374696f6e20776974682073616d652066756e6374696f6e000000000000000060608201526000608082019050919050565b60208152603660208201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260408201527f657373206d75737420626520616464726573732830290000000000000000000060608201526000608082019050919050565b6000825162001fcb81846020870162001981565b80830191505092915050565b60018060a01b038316815260406020820152600062001ffa604083018462001b5c565b90509392505050565b60208152603760208201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360408201527f74696f6e207468617420646f65736e277420657869737400000000000000000060608201526000608082019050919050565b60208152602e60208201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560408201527f7461626c652066756e6374696f6e00000000000000000000000000000000000060608201526000608082019050919050565b6000828203905081811115620020e657620020e562001c4b565b5b92915050565b634e487b7160e01b600052603160045260246000fd5b60208152600062002117602083018462001b5c565b905092915050565b611b4b806200212f6000396000f3fe60806040523661000b57005b6000807f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f9050809150600082600001600080357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610141576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610138906114d3565b60405180910390fd5b3660008037600080366000845af43d6000803e8060008114610162573d6000f35b3d6000fd5b806101706103c0565b60010160016101000a81548163ffffffff021916908360e01c021790555050565b60005b83518110156103755760008482815181106101b2576101b1611510565b5b6020026020010151602001519050600060028111156101d4576101d3611526565b5b8160028111156101e7576101e6611526565b5b036102375761023285838151811061020257610201611510565b5b60200260200101516000015186848151811061022157610220611510565b5b6020026020010151604001516103c5565b610361565b6001600281111561024b5761024a611526565b5b81600281111561025e5761025d611526565b5b036102ae576102a985838151811061027957610278611510565b5b60200260200101516000015186848151811061029857610297611510565b5b60200260200101516040015161063c565b610360565b6002808111156102c1576102c0611526565b5b8160028111156102d4576102d3611526565b5b036103245761031f8583815181106102ef576102ee611510565b5b60200260200101516000015186848151811061030e5761030d611510565b5b6020026020010151604001516108bd565b61035f565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103569061153c565b60405180910390fd5b5b5b50808061036d906115b6565b915050610194565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738383836040516103a99392919061163b565b60405180910390a16103bb8282610a48565b505050565b600090565b6000815111610409576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040090611747565b60405180910390fd5b6000610413610b6a565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047b906117ab565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff16036104f1576104f08285610b97565b5b60005b835181101561063557600084828151811061051257610511611510565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610606576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105fd9061180f565b60405180910390fd5b6106128583868a610c72565b838061061d90611873565b9450505050808061062d906115b6565b9150506104f4565b5050505050565b6000815111610680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067790611747565b60405180910390fd5b600061068a610b6a565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106f2906117ab565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff1603610768576107678285610b97565b5b60005b83518110156108b657600084828151811061078957610788611510565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361087c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610873906118a2565b60405180910390fd5b610887858284610e1f565b6108938583868a610c72565b838061089e90611873565b945050505080806108ae906115b6565b91505061076b565b5050505050565b6000815111610901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f890611747565b60405180910390fd5b600061090b610b6a565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461097c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097390611906565b60405180910390fd5b60005b8251811015610a4257600083828151811061099d5761099c611510565b5b602002602001015190506000836000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610a2d848284610e1f565b50508080610a3a906115b6565b91505061097f565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160315610b6657610a9f82604051806060016040528060288152602001611aca60289139611481565b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051610ac7919061196a565b600060405180830381855af49150503d8060008114610b02576040519150601f19603f3d011682016040523d82523d6000602084013e610b07565b606091505b509150915081610b6357600081511115610b245780518082602001fd5b83836040517f192105d7000000000000000000000000000000000000000000000000000000008152600401610b5a929190611988565b60405180910390fd5b50505b5050565b6000807f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f90508091505090565b610bb981604051806060016040528060248152602001611af260249139611481565b81600201805490508260010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555081600201819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b81846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508360010160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018390806001815401808255809150506001900390600052602060002090600891828204019190066004029091909190916101000a81548163ffffffff021916908360e01c021790555080846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e8e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e85906119b2565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610efc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef390611a16565b60405180910390fd5b6000836000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff169050600060018560010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000180549050610fd39190611a7a565b90508082146111675760008560010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001828154811061103457611033611510565b5b90600052602060002090600891828204019190066004029054906101000a900460e01b9050808660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000184815481106110b0576110af611510565b5b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555082866000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505b8460010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054806111bb576111ba611a98565b5b60019003818190600052602060002090600891828204019190066004026101000a81549063ffffffff02191690559055846000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a8154906bffffffffffffffffffffffff021916905550506000810361147a576000600186600201805490506112a59190611a7a565b905060008660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015490508181146113e657600087600201838154811061130f5761130e611510565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508088600201838154811061135357611352611510565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818860010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505b866002018054806113fa576113f9611a98565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000905550505b5050505050565b6000823b90506000811182906114cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114c49190611aae565b60405180910390fd5b50505050565b602081526020808201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460408201526000606082019050919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60208152602760208201527f4c69624469616d6f6e644375743a20496e636f7272656374204661636574437560408201527f74416374696f6e0000000000000000000000000000000000000000000000000060608201526000608082019050919050565b634e487b7160e01b600052601160045260246000fd5b6000801982036115c9576115c86115a0565b5b600182019050919050565b60018060a01b03811682525050565b60005b838110156116015780820151818401526020810190506115e6565b50600083830152505050565b600081518084526116258160208601602086016115e3565b6020601f19601f83011685010191505092915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b8481101561171757607f198a8503018652815188850160018060a01b03825116865284820151600381106116a857634e487b7160e01b600052602160045260246000fd5b80868801525060408083015192508a81880152508082518083528a880191508684019350600092505b808310156116fb5763ffffffff60e01b8451168252868201915086840193506001830192506116d1565b5080965050505082820191508286019550600181019050611664565b50506117258189018b6115d4565b508681036040880152611738818961160d565b95505050505050949350505050565b60208152602b60208201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201527f6163657420746f2063757400000000000000000000000000000000000000000060608201526000608082019050919050565b60208152602c60208201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201527f652061646472657373283029000000000000000000000000000000000000000060608201526000608082019050919050565b60208152603560208201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60408201527f6e207468617420616c726561647920657869737473000000000000000000000060608201526000608082019050919050565b60006bffffffffffffffffffffffff808316818103611895576118946115a0565b5b6001810192505050919050565b60208152603860208201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60408201527f6374696f6e20776974682073616d652066756e6374696f6e000000000000000060608201526000608082019050919050565b60208152603660208201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260408201527f657373206d75737420626520616464726573732830290000000000000000000060608201526000608082019050919050565b6000825161197c8184602087016115e3565b80830191505092915050565b60018060a01b03831681526040602082015260006119a9604083018461160d565b90509392505050565b60208152603760208201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360408201527f74696f6e207468617420646f65736e277420657869737400000000000000000060608201526000608082019050919050565b60208152602e60208201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560408201527f7461626c652066756e6374696f6e00000000000000000000000000000000000060608201526000608082019050919050565b6000828203905081811115611a9257611a916115a0565b5b92915050565b634e487b7160e01b600052603160045260246000fd5b602081526000611ac1602083018461160d565b90509291505056fe4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a264697066735822122045b771fb2128a1a34c5b052e9a86464933844b34929cf0d65bbea6a4e76e3b2764736f6c634300081200334c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465");
input.set_public_key("0xB5547FBdC56DCE45e1B8ef75569916D438e09c46");
+ input.set_salt(0);
// C++
{
@@ -68,6 +90,33 @@ TEST(Barz, GetCounterfactualAddress) {
}
}
+TEST(Barz, GetCounterfactualAddressNonZeroSalt) {
+ TW::Barz::Proto::ContractAddressInput input;
+ input.set_factory("0x96C489979E39F877BDb8637b75A25C1a5B2DE14C");
+ input.set_account_facet("0xF6F5e5fC74905e65e3FF53c6BacEba8535dd14d1");
+ input.set_verification_facet("0xaB84813cbf26Fd951CB3d7E33Dccb8995027e490");
+ input.set_entry_point("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789");
+ input.set_facet_registry("0x9a95d201BB8F559771784D12c01F8084278c65E5");
+ input.set_default_fallback("0x522cDc7558b5f798dF5D61AB09B6D95Ebd342EF9");
+ input.set_bytecode("0x60806040526040516104c83803806104c883398101604081905261002291610163565b6000858585858560405160240161003d959493929190610264565b60408051601f198184030181529181526020820180516001600160e01b0316634a93641760e01b1790525190915060009081906001600160a01b038a16906100869085906102c3565b600060405180830381855af49150503d80600081146100c1576040519150601f19603f3d011682016040523d82523d6000602084013e6100c6565b606091505b50915091508115806100e157506100dc816102df565b600114155b156100ff57604051636ff35f8960e01b815260040160405180910390fd5b505050505050505050610306565b80516001600160a01b038116811461012457600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561015a578181015183820152602001610142565b50506000910152565b60008060008060008060c0878903121561017c57600080fd5b6101858761010d565b95506101936020880161010d565b94506101a16040880161010d565b93506101af6060880161010d565b92506101bd6080880161010d565b60a08801519092506001600160401b03808211156101da57600080fd5b818901915089601f8301126101ee57600080fd5b81518181111561020057610200610129565b604051601f8201601f19908116603f0116810190838211818310171561022857610228610129565b816040528281528c602084870101111561024157600080fd5b61025283602083016020880161013f565b80955050505050509295509295509295565b600060018060a01b0380881683528087166020840152808616604084015280851660608401525060a0608083015282518060a08401526102ab8160c085016020870161013f565b601f01601f19169190910160c0019695505050505050565b600082516102d581846020870161013f565b9190910192915050565b80516020808301519190811015610300576000198160200360031b1b821691505b50919050565b6101b3806103156000396000f3fe60806040523661000b57005b600080356001600160e01b03191681527f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f6020819052604090912054819060601c806100cf576004838101546040516366ffd66360e11b81526000356001600160e01b031916928101929092526001600160a01b03169063cdffacc690602401602060405180830381865afa1580156100a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100cc919061014d565b90505b6001600160a01b0381166101295760405162461bcd60e51b815260206004820152601d60248201527f4261727a3a2046756e6374696f6e20646f6573206e6f74206578697374000000604482015260640160405180910390fd5b3660008037600080366000845af43d6000803e808015610148573d6000f35b3d6000fd5b60006020828403121561015f57600080fd5b81516001600160a01b038116811461017657600080fd5b939250505056fea2646970667358221220d35db061bb6ecdb7688c3674af669ce44d527cae4ded59214d06722d73da62be64736f6c63430008120033");
+ input.set_public_key("0xB5547FBdC56DCE45e1B8ef75569916D438e09c46");
+ input.set_salt(123456);
+
+ // C++
+ {
+ const std::string& address = getCounterfactualAddress(input);
+ ASSERT_EQ(address, "0xB91aaa96B138A1B1D94c9df4628187132c5F2bf1");
+ }
+
+ // C
+ {
+ const auto inputData = input.SerializeAsString();
+ const auto inputTWData = WRAPD(TWDataCreateWithBytes((const uint8_t *)inputData.data(), inputData.size()));
+ const auto& result = WRAPS(TWBarzGetCounterfactualAddress(inputTWData.get()));
+ assertStringsEqual(result, "0xB91aaa96B138A1B1D94c9df4628187132c5F2bf1");
+ }
+}
+
TEST(Barz, GetFormattedSignature) {
// C++
{
@@ -157,7 +206,8 @@ TEST(Barz, SignR1TransferAccountNotDeployed) {
auto factory = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800";
auto verificationFacet = "0x5034534Efe9902779eD6eA6983F435c00f3bc510";
auto publicKey = PublicKey(parse_hex("0x04b173a6a812025c40c38bac46343646bd0a8137c807aae6e04aac238cc24d2ad2116ca14d23d357588ff2aabd7db29d5976f4ecc8037775db86f67e873a306b1f"), TWPublicKeyTypeNIST256p1Extended);
- auto initCode = Barz::getInitCode(factory, publicKey, verificationFacet);
+ auto salt = 0;
+ auto initCode = Barz::getInitCode(factory, publicKey, verificationFacet, salt);
auto key = parse_hex("0x3c90badc15c4d35733769093d3733501e92e7f16e101df284cee9a310d36c483");
diff --git a/tests/chains/Ethereum/ContractCallTests.cpp b/tests/chains/Ethereum/ContractCallTests.cpp
index ca3108d4a05..19af2d14dbf 100644
--- a/tests/chains/Ethereum/ContractCallTests.cpp
+++ b/tests/chains/Ethereum/ContractCallTests.cpp
@@ -217,4 +217,18 @@ TEST(ContractCall, TupleNested) {
EXPECT_EQ(decoded.value(), expected);
}
+TEST(ContractCall, TupleArray) {
+ auto abiPath = TESTS_ROOT + "/chains/Ethereum/Data/swap_v2.json";
+ auto decodedPath = TESTS_ROOT + "/chains/Ethereum/Data/swap_v2_decoded.json";
+ auto abi = load_json(abiPath);
+ auto expectedJson = load_json(decodedPath);
+
+ auto call = parse_hex("846a1bc6000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000820000000000000000000000000a140f413c63fbda84e9008607e678258fffbc76b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000099a58482bd75cbab83b27ec03ca68ff489b5788f00000000000000000000000000000000000000000000000000470de4df820000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099a58482bd75cbab83b27ec03ca68ff489b5788f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000003840651cb35000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c7000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000000298ce42936ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d66600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000762696e616e636500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a307863653136463639333735353230616230313337376365374238386635424138433438463844363636000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000a140f413c63fbda84e9008607e678258fffbc76b000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf300000000000000000000000000000000000000000000000000000000000000010000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb1400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000104414bf3890000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf300000000000000000000000055d398326f99059ff775485246999027b319795500000000000000000000000000000000000000000000000000000000000000640000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd300000000000000000000000000000000000000000000000000000189c04a7044000000000000000000000000000000000000000000000000000029a23529cf68000000000000000000000000000000000000000000005af4f3f913bd553d03b900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf30000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000100000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000104414bf38900000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c00000000000000000000000000000000000000000000000000000000000001f40000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd300000000000000000000000000000000000000000000000000000189c04a7045000000000000000000000000000000000000000000005b527785e694f805bdd300000000000000000000000000000000000000000000005f935a1fa5c4a6ec61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000055d398326f99059ff775485246999027b319795500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000242e1a7d4d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a140f413c63fbda84e9008607e678258fffbc76b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
+ auto decoded = decodeCall(call, abi);
+ ASSERT_TRUE(decoded.has_value());
+
+ nlohmann::json parsedJson = nlohmann::json::parse(decoded.value());
+ EXPECT_EQ(parsedJson, expectedJson);
+}
+
} // namespace TW::Ethereum::ABI::tests
diff --git a/tests/chains/Ethereum/Data/swap_v2.json b/tests/chains/Ethereum/Data/swap_v2.json
new file mode 100644
index 00000000000..3651cd7b1ac
--- /dev/null
+++ b/tests/chains/Ethereum/Data/swap_v2.json
@@ -0,0 +1,70 @@
+{
+ "846a1bc6":{
+ "inputs":[
+ {
+ "name":"token",
+ "type":"address"
+ },
+ {
+ "name":"amount",
+ "type":"uint256"
+ },
+ {
+ "components":[
+ {
+ "name":"callType",
+ "type":"uint8"
+ },
+ {
+ "name":"target",
+ "type":"address"
+ },
+ {
+ "name":"value",
+ "type":"uint256"
+ },
+ {
+ "name":"callData",
+ "type":"bytes"
+ },
+ {
+ "name":"payload",
+ "type":"bytes"
+ }
+ ],
+ "name":"calls",
+ "type":"tuple[]"
+ },
+ {
+ "name":"bridgedTokenSymbol",
+ "type":"string"
+ },
+ {
+ "name":"destinationChain",
+ "type":"string"
+ },
+ {
+ "name":"destinationAddress",
+ "type":"string"
+ },
+ {
+ "name":"payload",
+ "type":"bytes"
+ },
+ {
+ "name":"gasRefundRecipient",
+ "type":"address"
+ },
+ {
+ "name":"enableExpress",
+ "type":"bool"
+ }
+ ],
+ "name":"callBridgeCall",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ }
+}
\ No newline at end of file
diff --git a/tests/chains/Ethereum/Data/swap_v2_decoded.json b/tests/chains/Ethereum/Data/swap_v2_decoded.json
new file mode 100644
index 00000000000..49a95d7806e
--- /dev/null
+++ b/tests/chains/Ethereum/Data/swap_v2_decoded.json
@@ -0,0 +1,105 @@
+{
+ "function": "callBridgeCall(address,uint256,(uint8,address,uint256,bytes,bytes)[],string,string,string,bytes,address,bool)",
+ "inputs": [
+ {
+ "name": "token",
+ "type": "address",
+ "value": "0xdac17f958d2ee523a2206206994597c13d831ec7"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "value": "20000000000000000"
+ },
+ {
+ "components": [
+ [
+ {
+ "name": "callType",
+ "type": "uint8",
+ "value": "0"
+ },
+ {
+ "name": "target",
+ "type": "address",
+ "value": "0xdac17f958d2ee523a2206206994597c13d831ec7"
+ },
+ {
+ "name": "value",
+ "type": "uint256",
+ "value": "0"
+ },
+ {
+ "name": "callData",
+ "type": "bytes",
+ "value": "0x095ea7b300000000000000000000000099a58482bd75cbab83b27ec03ca68ff489b5788f00000000000000000000000000000000000000000000000000470de4df820000"
+ },
+ {
+ "name": "payload",
+ "type": "bytes",
+ "value": "0x"
+ }
+ ],
+ [
+ {
+ "name": "callType",
+ "type": "uint8",
+ "value": "0"
+ },
+ {
+ "name": "target",
+ "type": "address",
+ "value": "0x99a58482bd75cbab83b27ec03ca68ff489b5788f"
+ },
+ {
+ "name": "value",
+ "type": "uint256",
+ "value": "0"
+ },
+ {
+ "name": "callData",
+ "type": "bytes",
+ "value": "0x0651cb35000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c7000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000000298ce42936ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d666"
+ },
+ {
+ "name": "payload",
+ "type": "bytes",
+ "value": "0x"
+ }
+ ]
+ ],
+ "name": "calls",
+ "type": "tuple[]"
+ },
+ {
+ "name": "bridgedTokenSymbol",
+ "type": "string",
+ "value": "USDC"
+ },
+ {
+ "name": "destinationChain",
+ "type": "string",
+ "value": "binance"
+ },
+ {
+ "name": "destinationAddress",
+ "type": "string",
+ "value": "0xce16F69375520ab01377ce7B88f5BA8C48F8D666"
+ },
+ {
+ "name": "payload",
+ "type": "bytes",
+ "value": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000a140f413c63fbda84e9008607e678258fffbc76b000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf300000000000000000000000000000000000000000000000000000000000000010000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb1400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000104414bf3890000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf300000000000000000000000055d398326f99059ff775485246999027b319795500000000000000000000000000000000000000000000000000000000000000640000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd300000000000000000000000000000000000000000000000000000189c04a7044000000000000000000000000000000000000000000000000000029a23529cf68000000000000000000000000000000000000000000005af4f3f913bd553d03b900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf30000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000100000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000001b81d678ffb9c0263b24a97847620c99d213eb14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000104414bf38900000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c00000000000000000000000000000000000000000000000000000000000001f40000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd300000000000000000000000000000000000000000000000000000189c04a7045000000000000000000000000000000000000000000005b527785e694f805bdd300000000000000000000000000000000000000000000005f935a1fa5c4a6ec61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000055d398326f99059ff775485246999027b319795500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000242e1a7d4d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a140f413c63fbda84e9008607e678258fffbc76b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ },
+ {
+ "name": "gasRefundRecipient",
+ "type": "address",
+ "value": "0xa140f413c63fbda84e9008607e678258fffbc76b"
+ },
+ {
+ "name": "enableExpress",
+ "type": "bool",
+ "value": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/common/CoinAddressDerivationTests.cpp b/tests/common/CoinAddressDerivationTests.cpp
index ac948f7aa11..0a242324f7c 100644
--- a/tests/common/CoinAddressDerivationTests.cpp
+++ b/tests/common/CoinAddressDerivationTests.cpp
@@ -78,6 +78,7 @@ TEST(Coin, DeriveAddress) {
case TWCoinTypeScroll:
case TWCoinTypeOpBNBtestnet:
case TWCoinTypeNeon:
+ case TWCoinTypeBase:
EXPECT_EQ(address, "0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F");
break;
diff --git a/wasm/tests/Blockchain/Bitcoin.test.ts b/wasm/tests/Blockchain/Bitcoin.test.ts
index d516512bb54..270f774d86f 100644
--- a/wasm/tests/Blockchain/Bitcoin.test.ts
+++ b/wasm/tests/Blockchain/Bitcoin.test.ts
@@ -202,4 +202,14 @@ describe("Bitcoin", () => {
assert.isTrue(outputHex.endsWith("5b0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800377b2270223a226272632d3230222c226f70223a227472616e73666572222c227469636b223a226f616466222c22616d74223a223230227d6821c00f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000"))
assert.equal(output.transactionId, "7046dc2689a27e143ea2ad1039710885147e9485ab6453fa7e87464aa7dd3eca");
});
+
+ it("test Bitcoin calculate BRC20 Commit fee", () => {
+ const { BitcoinFee, HexCoding } = globalThis.core;
+
+ const rawTx = HexCoding.decode("02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000");
+ const satVb = "19";
+
+ const fee = BitcoinFee.calculateFee(rawTx, satVb);
+ assert.equal(fee, "2907") // 19*153
+ });
});