#473 erc20-support
This commit is contained in:
parent
cb60cbe5d1
commit
0b64f0cfcc
14 changed files with 329 additions and 83 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
#include <graphene/peerplays_sidechain/common/utils.hpp>
|
#include <graphene/peerplays_sidechain/common/utils.hpp>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
|
|
@ -47,4 +48,17 @@ std::string object_id_to_string(graphene::chain::object_id_type id) {
|
||||||
return object_id;
|
return object_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
graphene::chain::object_id_type string_to_object_id(const std::string &id) {
|
||||||
|
std::vector<std::string> strs;
|
||||||
|
boost::split(strs, id, boost::is_any_of("."));
|
||||||
|
if (strs.size() != 3) {
|
||||||
|
elog("Wrong object_id format: ${id}", ("id", id));
|
||||||
|
return graphene::chain::object_id_type{};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto s = boost::lexical_cast<int>(strs.at(0));
|
||||||
|
auto t = boost::lexical_cast<int>(strs.at(1));
|
||||||
|
return graphene::chain::object_id_type{(uint8_t)s, (uint8_t)t, boost::lexical_cast<uint64_t>(strs.at(2))};
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace graphene::peerplays_sidechain
|
}} // namespace graphene::peerplays_sidechain
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,51 @@
|
||||||
|
|
||||||
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
|
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
|
||||||
|
|
||||||
//! rlp_decoder
|
//! base_decoder
|
||||||
|
boost::multiprecision::uint256_t base_decoder::decode_uint256(const std::string &value) {
|
||||||
|
boost::multiprecision::uint256_t result = 0;
|
||||||
|
|
||||||
|
boost::multiprecision::uint256_t power(1);
|
||||||
|
uint8_t digit;
|
||||||
|
int pos = value.size() - 1;
|
||||||
|
while (pos >= 0) {
|
||||||
|
digit = 0;
|
||||||
|
if ('0' <= value[pos] && value[pos] <= '9') {
|
||||||
|
digit = value[pos] - '0';
|
||||||
|
} else if ('a' <= value[pos] && value[pos] <= 'z') {
|
||||||
|
digit = value[pos] - 'a' + 10;
|
||||||
|
}
|
||||||
|
result += digit * power;
|
||||||
|
pos--;
|
||||||
|
power *= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string base_decoder::decode_address(const std::string &value) {
|
||||||
|
return value.substr(24, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! deposit_erc20_decoder
|
||||||
|
const std::string deposit_erc20_decoder::function_signature = "97feb926"; //! depositERC20(address,uint256)
|
||||||
|
fc::optional<deposit_erc20_transaction> deposit_erc20_decoder::decode(const std::string &input) {
|
||||||
|
const auto input_without_0x = remove_0x(input);
|
||||||
|
if (function_signature != input_without_0x.substr(0, 8)) {
|
||||||
|
return fc::optional<deposit_erc20_transaction>{};
|
||||||
|
}
|
||||||
|
if (input_without_0x.size() != 136) {
|
||||||
|
return fc::optional<deposit_erc20_transaction>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
deposit_erc20_transaction erc_20;
|
||||||
|
erc_20.token = add_0x(base_decoder::decode_address(input_without_0x.substr(8, 64)));
|
||||||
|
erc_20.amount = base_decoder::decode_uint256(input_without_0x.substr(72, 64));
|
||||||
|
|
||||||
|
return erc_20;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! rlp_decoder
|
||||||
namespace {
|
namespace {
|
||||||
const signed char p_util_hexdigit[256] =
|
const signed char p_util_hexdigit[256] =
|
||||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ std::string base_encoder::encode_string(const std::string &value) {
|
||||||
//! update_owners_encoder
|
//! update_owners_encoder
|
||||||
const std::string update_owners_encoder::function_signature = "23ab6adf"; //! updateOwners((address,uint256)[],string)
|
const std::string update_owners_encoder::function_signature = "23ab6adf"; //! updateOwners((address,uint256)[],string)
|
||||||
std::string update_owners_encoder::encode(const std::vector<std::pair<std::string, uint16_t>> &owners_weights, const std::string &object_id) {
|
std::string update_owners_encoder::encode(const std::vector<std::pair<std::string, uint16_t>> &owners_weights, const std::string &object_id) {
|
||||||
std::string data = "0x" + function_signature;
|
std::string data = add_0x(function_signature);
|
||||||
data += base_encoder::encode_uint256(64);
|
data += base_encoder::encode_uint256(64);
|
||||||
data += base_encoder::encode_uint256((owners_weights.size() * 2 + 3) * 32);
|
data += base_encoder::encode_uint256((owners_weights.size() * 2 + 3) * 32);
|
||||||
data += base_encoder::encode_uint256(owners_weights.size());
|
data += base_encoder::encode_uint256(owners_weights.size());
|
||||||
|
|
@ -44,7 +44,7 @@ std::string update_owners_encoder::encode(const std::vector<std::pair<std::strin
|
||||||
//! withdrawal_encoder
|
//! withdrawal_encoder
|
||||||
const std::string withdrawal_encoder::function_signature = "e088747b"; //! withdraw(address,uint256,string)
|
const std::string withdrawal_encoder::function_signature = "e088747b"; //! withdraw(address,uint256,string)
|
||||||
std::string withdrawal_encoder::encode(const std::string &to, boost::multiprecision::uint256_t amount, const std::string &object_id) {
|
std::string withdrawal_encoder::encode(const std::string &to, boost::multiprecision::uint256_t amount, const std::string &object_id) {
|
||||||
std::string data = "0x" + function_signature;
|
std::string data = add_0x(function_signature);
|
||||||
data += base_encoder::encode_address(to);
|
data += base_encoder::encode_address(to);
|
||||||
data += base_encoder::encode_uint256(amount);
|
data += base_encoder::encode_uint256(amount);
|
||||||
data += base_encoder::encode_uint256(32 * 3);
|
data += base_encoder::encode_uint256(32 * 3);
|
||||||
|
|
@ -53,7 +53,23 @@ std::string withdrawal_encoder::encode(const std::string &to, boost::multiprecis
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! withdrawal_erc20_encoder
|
||||||
|
const std::string withdrawal_erc20_encoder::function_signature = "483c0467"; //! withdrawERC20(address,address,uint256,string)
|
||||||
|
std::string withdrawal_erc20_encoder::encode(const std::string &token, const std::string &to, boost::multiprecision::uint256_t amount, const std::string &object_id) {
|
||||||
|
std::string data = add_0x(function_signature);
|
||||||
|
data += base_encoder::encode_address(token);
|
||||||
|
data += base_encoder::encode_address(to);
|
||||||
|
data += base_encoder::encode_uint256(amount);
|
||||||
|
data += base_encoder::encode_uint256(32 * 4);
|
||||||
|
data += base_encoder::encode_string(object_id);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
//! signature_encoder
|
//! signature_encoder
|
||||||
|
const std::string update_owners_function_signature = "9d608673"; //! updateOwners((bytes,(uint8,bytes32,bytes32))[])
|
||||||
|
const std::string withdrawal_function_signature = "daac6c81"; //! withdraw((bytes,(uint8,bytes32,bytes32))[])
|
||||||
|
const std::string withdrawal_erc20_function_signature = "d2bf2866"; //! withdrawERC20((bytes,(uint8,bytes32,bytes32))[])
|
||||||
signature_encoder::signature_encoder(const std::string &function_hash) :
|
signature_encoder::signature_encoder(const std::string &function_hash) :
|
||||||
function_signature{function_hash} {
|
function_signature{function_hash} {
|
||||||
}
|
}
|
||||||
|
|
@ -66,11 +82,14 @@ std::string signature_encoder::get_function_signature_from_transaction(const std
|
||||||
if (tr.substr(0, 8) == withdrawal_encoder::function_signature)
|
if (tr.substr(0, 8) == withdrawal_encoder::function_signature)
|
||||||
return withdrawal_function_signature;
|
return withdrawal_function_signature;
|
||||||
|
|
||||||
|
if (tr.substr(0, 8) == withdrawal_erc20_encoder::function_signature)
|
||||||
|
return withdrawal_erc20_function_signature;
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string signature_encoder::encode(const std::vector<encoded_sign_transaction> &transactions) const {
|
std::string signature_encoder::encode(const std::vector<encoded_sign_transaction> &transactions) const {
|
||||||
std::string data = "0x" + function_signature;
|
std::string data = add_0x(function_signature);
|
||||||
data += base_encoder::encode_uint256(32);
|
data += base_encoder::encode_uint256(32);
|
||||||
data += base_encoder::encode_uint256(transactions.size());
|
data += base_encoder::encode_uint256(transactions.size());
|
||||||
size_t offset = (transactions.size()) * 32;
|
size_t offset = (transactions.size()) * 32;
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,6 @@ std::string base64_encode(const std::string &s);
|
||||||
std::string base64_decode(const std::string &s);
|
std::string base64_decode(const std::string &s);
|
||||||
|
|
||||||
std::string object_id_to_string(graphene::chain::object_id_type id);
|
std::string object_id_to_string(graphene::chain::object_id_type id);
|
||||||
|
graphene::chain::object_id_type string_to_object_id(const std::string &id);
|
||||||
|
|
||||||
}} // namespace graphene::peerplays_sidechain
|
}} // namespace graphene::peerplays_sidechain
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,16 @@ struct info_for_vin {
|
||||||
bool resend = false;
|
bool resend = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class sidechain_event_type {
|
||||||
|
deposit,
|
||||||
|
withdrawal
|
||||||
|
};
|
||||||
|
|
||||||
struct sidechain_event_data {
|
struct sidechain_event_data {
|
||||||
fc::time_point_sec timestamp;
|
fc::time_point_sec timestamp;
|
||||||
uint32_t block_num;
|
uint32_t block_num;
|
||||||
sidechain_type sidechain;
|
sidechain_type sidechain;
|
||||||
|
sidechain_event_type type;
|
||||||
std::string sidechain_uid;
|
std::string sidechain_uid;
|
||||||
std::string sidechain_transaction_id;
|
std::string sidechain_transaction_id;
|
||||||
std::string sidechain_from;
|
std::string sidechain_from;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,31 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/multiprecision/cpp_int.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fc/optional.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
|
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
|
||||||
|
|
||||||
|
class base_decoder {
|
||||||
|
public:
|
||||||
|
static boost::multiprecision::uint256_t decode_uint256(const std::string &value);
|
||||||
|
static std::string decode_address(const std::string &value);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct deposit_erc20_transaction {
|
||||||
|
std::string token;
|
||||||
|
boost::multiprecision::uint256_t amount;
|
||||||
|
};
|
||||||
|
|
||||||
|
class deposit_erc20_decoder {
|
||||||
|
public:
|
||||||
|
static const std::string function_signature;
|
||||||
|
|
||||||
|
static fc::optional<deposit_erc20_transaction> decode(const std::string &input);
|
||||||
|
};
|
||||||
|
|
||||||
class rlp_decoder {
|
class rlp_decoder {
|
||||||
private:
|
private:
|
||||||
enum RLP_constants {
|
enum RLP_constants {
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,6 @@
|
||||||
|
|
||||||
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
|
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
|
||||||
|
|
||||||
const std::string update_owners_function_signature = "9d608673"; //! updateOwners((bytes,(uint8,bytes32,bytes32))[])
|
|
||||||
const std::string withdrawal_function_signature = "daac6c81"; //! withdraw((bytes,(uint8,bytes32,bytes32))[])
|
|
||||||
|
|
||||||
struct encoded_sign_transaction {
|
struct encoded_sign_transaction {
|
||||||
std::string data;
|
std::string data;
|
||||||
signature sign;
|
signature sign;
|
||||||
|
|
@ -37,6 +34,13 @@ public:
|
||||||
static std::string encode(const std::string &to, boost::multiprecision::uint256_t amount, const std::string &object_id);
|
static std::string encode(const std::string &to, boost::multiprecision::uint256_t amount, const std::string &object_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class withdrawal_erc20_encoder {
|
||||||
|
public:
|
||||||
|
static const std::string function_signature;
|
||||||
|
|
||||||
|
static std::string encode(const std::string &token, const std::string &to, boost::multiprecision::uint256_t amount, const std::string &object_id);
|
||||||
|
};
|
||||||
|
|
||||||
class signature_encoder {
|
class signature_encoder {
|
||||||
public:
|
public:
|
||||||
const std::string function_signature;
|
const std::string function_signature;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/bimap.hpp>
|
||||||
#include <boost/signals2.hpp>
|
#include <boost/signals2.hpp>
|
||||||
|
|
||||||
#include <graphene/peerplays_sidechain/common/rpc_client.hpp>
|
#include <graphene/peerplays_sidechain/common/rpc_client.hpp>
|
||||||
|
|
@ -52,11 +53,15 @@ public:
|
||||||
bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount);
|
bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount);
|
||||||
virtual optional<asset> estimate_withdrawal_transaction_fee() const override;
|
virtual optional<asset> estimate_withdrawal_transaction_fee() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using bimap_type = boost::bimap<std::string, std::string>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string rpc_url;
|
std::string rpc_url;
|
||||||
std::string rpc_user;
|
std::string rpc_user;
|
||||||
std::string rpc_password;
|
std::string rpc_password;
|
||||||
std::string wallet_contract_address;
|
std::string wallet_contract_address;
|
||||||
|
bimap_type erc20_addresses;
|
||||||
|
|
||||||
ethereum_rpc_client *rpc_client;
|
ethereum_rpc_client *rpc_client;
|
||||||
|
|
||||||
|
|
@ -64,7 +69,6 @@ private:
|
||||||
ethereum::network_id_type network_id;
|
ethereum::network_id_type network_id;
|
||||||
|
|
||||||
std::string create_primary_wallet_transaction(const std::vector<son_info> &son_pubkeys, const std::string &object_id);
|
std::string create_primary_wallet_transaction(const std::vector<son_info> &son_pubkeys, const std::string &object_id);
|
||||||
std::string create_deposit_transaction(const son_wallet_deposit_object &swdo);
|
|
||||||
std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo);
|
std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo);
|
||||||
|
|
||||||
std::string sign_transaction(const sidechain_transaction_object &sto);
|
std::string sign_transaction(const sidechain_transaction_object &sto);
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,8 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
||||||
cli.add_options()("ethereum-node-rpc-user", bpo::value<string>(), "Ethereum RPC user");
|
cli.add_options()("ethereum-node-rpc-user", bpo::value<string>(), "Ethereum RPC user");
|
||||||
cli.add_options()("ethereum-node-rpc-password", bpo::value<string>(), "Ethereum RPC password");
|
cli.add_options()("ethereum-node-rpc-password", bpo::value<string>(), "Ethereum RPC password");
|
||||||
cli.add_options()("ethereum-wallet-contract-address", bpo::value<string>(), "Ethereum wallet contract address");
|
cli.add_options()("ethereum-wallet-contract-address", bpo::value<string>(), "Ethereum wallet contract address");
|
||||||
|
cli.add_options()("erc-20-address", bpo::value<vector<string>>()->composing()->multitoken(),
|
||||||
|
"Tuple of [ERC-20 symbol, ERC-20 address] (may specify multiple times)");
|
||||||
cli.add_options()("ethereum-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", "9bedac2bd8fe2a6f6528e066c67fc8ac0622e96828d40c0e820d83c5bd2b0589")),
|
cli.add_options()("ethereum-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", "9bedac2bd8fe2a6f6528e066c67fc8ac0622e96828d40c0e820d83c5bd2b0589")),
|
||||||
"Tuple of [Ethereum public key, Ethereum private key] (may specify multiple times)");
|
"Tuple of [Ethereum public key, Ethereum private key] (may specify multiple times)");
|
||||||
|
|
||||||
|
|
@ -630,6 +632,11 @@ std::map<sidechain_type, std::vector<std::string>> peerplays_sidechain_plugin_im
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<asset> peerplays_sidechain_plugin_impl::estimate_withdrawal_transaction_fee(sidechain_type sidechain) {
|
optional<asset> peerplays_sidechain_plugin_impl::estimate_withdrawal_transaction_fee(sidechain_type sidechain) {
|
||||||
|
if (net_handlers.count(sidechain) == 0) {
|
||||||
|
wlog("No net handler for sidechain: ${sidechain}", ("sidechain", sidechain));
|
||||||
|
return optional<asset>();
|
||||||
|
}
|
||||||
|
|
||||||
if (!net_handlers.at(sidechain)) {
|
if (!net_handlers.at(sidechain)) {
|
||||||
wlog("Net handler is null for sidechain: ${sidechain}", ("sidechain", sidechain));
|
wlog("Net handler is null for sidechain: ${sidechain}", ("sidechain", sidechain));
|
||||||
return optional<asset>();
|
return optional<asset>();
|
||||||
|
|
|
||||||
|
|
@ -190,22 +190,25 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
||||||
// (sed.sidechain_currency.compare("HIVE") != 0);
|
// (sed.sidechain_currency.compare("HIVE") != 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) &&
|
const bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) &&
|
||||||
(((sed.sidechain == sidechain_type::bitcoin) && (sed.sidechain_currency.compare("BTC") == 0)) ||
|
(sed.sidechain == sidechain) &&
|
||||||
((sed.sidechain == sidechain_type::ethereum) && (sed.sidechain_currency.compare("ETH") == 0)) ||
|
(sed.type == sidechain_event_type::deposit) &&
|
||||||
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HBD") == 0)) ||
|
(((sed.sidechain == sidechain_type::bitcoin) && (sed.sidechain_currency.compare("BTC") == 0)) ||
|
||||||
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) ||
|
((sed.sidechain == sidechain_type::ethereum) && (!sed.sidechain_currency.empty())) ||
|
||||||
enable_peerplays_asset_deposits);
|
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HBD") == 0)) ||
|
||||||
|
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) ||
|
||||||
|
enable_peerplays_asset_deposits);
|
||||||
|
|
||||||
bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain) && //! Fixme -> sidechain_type::peerplays
|
const bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) &&
|
||||||
((sed.sidechain_currency == object_id_to_string(gpo.parameters.btc_asset())) ||
|
(sed.sidechain == sidechain) &&
|
||||||
(sed.sidechain_currency == object_id_to_string(gpo.parameters.eth_asset())) ||
|
(sed.type == sidechain_event_type::withdrawal) &&
|
||||||
(sed.sidechain_currency == object_id_to_string(gpo.parameters.hbd_asset())) ||
|
(((sed.sidechain == sidechain_type::bitcoin) && (sed.sidechain_currency == object_id_to_string(gpo.parameters.btc_asset()))) ||
|
||||||
(sed.sidechain_currency == object_id_to_string(gpo.parameters.hive_asset())));
|
((sed.sidechain == sidechain_type::ethereum) && (!sed.sidechain_currency.empty())) ||
|
||||||
|
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency == object_id_to_string(gpo.parameters.hbd_asset()))) ||
|
||||||
|
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency == object_id_to_string(gpo.parameters.hive_asset()))));
|
||||||
|
|
||||||
// Deposit request
|
// Deposit request
|
||||||
if (deposit_condition) {
|
if (deposit_condition) {
|
||||||
|
|
||||||
for (son_id_type son_id : plugin.get_sons()) {
|
for (son_id_type son_id : plugin.get_sons()) {
|
||||||
if (plugin.is_active_son(sidechain, son_id)) {
|
if (plugin.is_active_son(sidechain, son_id)) {
|
||||||
|
|
||||||
|
|
@ -269,7 +272,17 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
||||||
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate;
|
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate;
|
||||||
}
|
}
|
||||||
if (withdraw_currency.empty()) {
|
if (withdraw_currency.empty()) {
|
||||||
return;
|
//! This is ERC-20 withdrawal
|
||||||
|
const auto asset_object_id = string_to_object_id(sed.sidechain_currency);
|
||||||
|
const auto &assets_by_id = database.get_index_type<asset_index>().indices().get<by_id>();
|
||||||
|
const auto asset_itr = assets_by_id.find(asset_object_id);
|
||||||
|
if (asset_itr == assets_by_id.end()) {
|
||||||
|
wlog("Could not find asset: ${asset_object_id}", ("asset_object_id", asset_object_id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
withdraw_currency = asset_itr->symbol;
|
||||||
|
withdraw_currency_price = asset_itr->options.core_exchange_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (son_id_type son_id : plugin.get_sons()) {
|
for (son_id_type son_id : plugin.get_sons()) {
|
||||||
|
|
@ -663,9 +676,10 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_tracked_asset =
|
const bool is_tracked_asset =
|
||||||
((sidechain == sidechain_type::bitcoin) && (transfer_op.amount.asset_id == gpo.parameters.btc_asset())) ||
|
((sidechain == sidechain_type::bitcoin) && (transfer_op.amount.asset_id == gpo.parameters.btc_asset())) ||
|
||||||
((sidechain == sidechain_type::ethereum) && (transfer_op.amount.asset_id == gpo.parameters.eth_asset())) ||
|
((sidechain == sidechain_type::ethereum) && (transfer_op.amount.asset_id == gpo.parameters.eth_asset())) ||
|
||||||
|
(sidechain == sidechain_type::ethereum) ||
|
||||||
((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hbd_asset())) ||
|
((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hbd_asset())) ||
|
||||||
((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hive_asset()));
|
((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hive_asset()));
|
||||||
|
|
||||||
|
|
@ -691,7 +705,8 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) {
|
||||||
sidechain_event_data sed;
|
sidechain_event_data sed;
|
||||||
sed.timestamp = database.head_block_time();
|
sed.timestamp = database.head_block_time();
|
||||||
sed.block_num = database.head_block_num();
|
sed.block_num = database.head_block_num();
|
||||||
sed.sidechain = sidechain; //! Fixme -> sidechain_type::peerplays
|
sed.sidechain = sidechain;
|
||||||
|
sed.type = sidechain_event_type::withdrawal;
|
||||||
sed.sidechain_uid = sidechain_uid;
|
sed.sidechain_uid = sidechain_uid;
|
||||||
sed.sidechain_transaction_id = trx.id().str();
|
sed.sidechain_transaction_id = trx.id().str();
|
||||||
sed.sidechain_from = sidechain_from;
|
sed.sidechain_from = sidechain_from;
|
||||||
|
|
|
||||||
|
|
@ -1282,6 +1282,7 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data)
|
||||||
sed.timestamp = database.head_block_time();
|
sed.timestamp = database.head_block_time();
|
||||||
sed.block_num = database.head_block_num();
|
sed.block_num = database.head_block_num();
|
||||||
sed.sidechain = addr_itr->sidechain;
|
sed.sidechain = addr_itr->sidechain;
|
||||||
|
sed.type = sidechain_event_type::deposit;
|
||||||
sed.sidechain_uid = sidechain_uid;
|
sed.sidechain_uid = sidechain_uid;
|
||||||
sed.sidechain_transaction_id = v.out.hash_tx;
|
sed.sidechain_transaction_id = v.out.hash_tx;
|
||||||
sed.sidechain_from = v.address;
|
sed.sidechain_from = v.address;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
#include <graphene/chain/sidechain_transaction_object.hpp>
|
#include <graphene/chain/sidechain_transaction_object.hpp>
|
||||||
#include <graphene/chain/son_info.hpp>
|
#include <graphene/chain/son_info.hpp>
|
||||||
#include <graphene/chain/son_wallet_object.hpp>
|
#include <graphene/chain/son_wallet_object.hpp>
|
||||||
|
#include <graphene/peerplays_sidechain/ethereum/decoders.hpp>
|
||||||
#include <graphene/peerplays_sidechain/ethereum/encoders.hpp>
|
#include <graphene/peerplays_sidechain/ethereum/encoders.hpp>
|
||||||
#include <graphene/peerplays_sidechain/ethereum/transaction.hpp>
|
#include <graphene/peerplays_sidechain/ethereum/transaction.hpp>
|
||||||
#include <graphene/peerplays_sidechain/ethereum/utils.hpp>
|
#include <graphene/peerplays_sidechain/ethereum/utils.hpp>
|
||||||
|
|
@ -147,6 +148,21 @@ sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidecha
|
||||||
|
|
||||||
wallet_contract_address = options.at("ethereum-wallet-contract-address").as<std::string>();
|
wallet_contract_address = options.at("ethereum-wallet-contract-address").as<std::string>();
|
||||||
|
|
||||||
|
if (options.count("erc-20-address")) {
|
||||||
|
const std::vector<std::string> symbol_addresses = options["erc-20-address"].as<std::vector<std::string>>();
|
||||||
|
for (const std::string &itr : symbol_addresses) {
|
||||||
|
auto itr_pair = graphene::app::dejsonify<std::pair<std::string, std::string>>(itr, 5);
|
||||||
|
ilog("ERC-20 symbol: ${symbol}, address: ${address}", ("symbol", itr_pair.first)("address", itr_pair.second));
|
||||||
|
if (!itr_pair.first.length() || !itr_pair.second.length()) {
|
||||||
|
FC_THROW("Invalid symbol address pair.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto address = itr_pair.second;
|
||||||
|
std::transform(address.begin(), address.end(), address.begin(), ::tolower);
|
||||||
|
erc20_addresses.insert(bimap_type::value_type{itr_pair.first, address});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options.count("ethereum-private-key")) {
|
if (options.count("ethereum-private-key")) {
|
||||||
const std::vector<std::string> pub_priv_keys = options["ethereum-private-key"].as<std::vector<std::string>>();
|
const std::vector<std::string> pub_priv_keys = options["ethereum-private-key"].as<std::vector<std::string>>();
|
||||||
for (const std::string &itr_key_pair : pub_priv_keys) {
|
for (const std::string &itr_key_pair : pub_priv_keys) {
|
||||||
|
|
@ -290,21 +306,41 @@ bool sidechain_net_handler_ethereum::process_proposal(const proposal_object &po)
|
||||||
|
|
||||||
const std::string sidechain_from = tx.get<std::string>("result.from");
|
const std::string sidechain_from = tx.get<std::string>("result.from");
|
||||||
const std::string sidechain_to = tx.get<std::string>("result.to");
|
const std::string sidechain_to = tx.get<std::string>("result.to");
|
||||||
const std::string value_s = tx.get<std::string>("result.value");
|
|
||||||
boost::multiprecision::uint256_t amount(value_s);
|
|
||||||
amount = amount / 100000;
|
|
||||||
amount = amount / 100000;
|
|
||||||
const fc::safe<uint64_t> sidechain_amount = amount;
|
|
||||||
|
|
||||||
std::string cmp_sidechain_to = sidechain_to;
|
std::string cmp_sidechain_to = sidechain_to;
|
||||||
std::transform(cmp_sidechain_to.begin(), cmp_sidechain_to.end(), cmp_sidechain_to.begin(), ::toupper);
|
std::transform(cmp_sidechain_to.begin(), cmp_sidechain_to.end(), cmp_sidechain_to.begin(), ::toupper);
|
||||||
std::string cmp_wallet_contract_address = wallet_contract_address;
|
std::string cmp_wallet_contract_address = wallet_contract_address;
|
||||||
std::transform(cmp_wallet_contract_address.begin(), cmp_wallet_contract_address.end(), cmp_wallet_contract_address.begin(), ::toupper);
|
std::transform(cmp_wallet_contract_address.begin(), cmp_wallet_contract_address.end(), cmp_wallet_contract_address.begin(), ::toupper);
|
||||||
|
|
||||||
process_ok = (swdo_sidechain_from == sidechain_from) &&
|
//! Check whether it is ERC-20 token deposit
|
||||||
|
std::string symbol;
|
||||||
|
boost::multiprecision::uint256_t amount;
|
||||||
|
bool error_in_deposit = false;
|
||||||
|
const auto deposit_erc_20 = ethereum::deposit_erc20_decoder::decode(tx.get<std::string>("result.input"));
|
||||||
|
if (deposit_erc_20.valid()) {
|
||||||
|
std::string cmp_token = deposit_erc_20->token;
|
||||||
|
std::transform(cmp_token.begin(), cmp_token.end(), cmp_token.begin(), ::tolower);
|
||||||
|
|
||||||
|
const auto it = erc20_addresses.right.find(cmp_token);
|
||||||
|
if (it == erc20_addresses.right.end()) {
|
||||||
|
wlog("No erc-20 token with address: ${address}", ("address", cmp_token));
|
||||||
|
error_in_deposit = true;
|
||||||
|
}
|
||||||
|
symbol = it->second;
|
||||||
|
amount = deposit_erc_20->amount;
|
||||||
|
} else {
|
||||||
|
symbol = "ETH";
|
||||||
|
const std::string value_s = tx.get<std::string>("result.value");
|
||||||
|
amount = boost::multiprecision::uint256_t{value_s};
|
||||||
|
amount = amount / 100000;
|
||||||
|
amount = amount / 100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_ok = (!error_in_deposit) &&
|
||||||
|
(swdo_sidechain_from == sidechain_from) &&
|
||||||
(cmp_sidechain_to == cmp_wallet_contract_address) &&
|
(cmp_sidechain_to == cmp_wallet_contract_address) &&
|
||||||
(swdo_sidechain_currency == "ETH") &&
|
(swdo_sidechain_currency == symbol) &&
|
||||||
(swdo_sidechain_amount == sidechain_amount.value);
|
(swdo_sidechain_amount == fc::safe<uint64_t>{amount}.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -427,7 +463,7 @@ void sidechain_net_handler_ethereum::process_primary_wallet() {
|
||||||
const chain::global_property_object &gpo = database.get_global_properties();
|
const chain::global_property_object &gpo = database.get_global_properties();
|
||||||
proposal_create_operation proposal_op;
|
proposal_create_operation proposal_op;
|
||||||
proposal_op.fee_paying_account = plugin.get_current_son_object(sidechain).son_account;
|
proposal_op.fee_paying_account = plugin.get_current_son_object(sidechain).son_account;
|
||||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
const uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||||
|
|
||||||
son_wallet_update_operation swu_op;
|
son_wallet_update_operation swu_op;
|
||||||
|
|
@ -489,12 +525,19 @@ bool sidechain_net_handler_ethereum::process_deposit(const son_wallet_deposit_ob
|
||||||
|
|
||||||
const chain::global_property_object &gpo = database.get_global_properties();
|
const chain::global_property_object &gpo = database.get_global_properties();
|
||||||
|
|
||||||
price asset_price = database.get<asset_object>(database.get_global_properties().parameters.eth_asset()).options.core_exchange_rate;
|
const auto &assets_by_symbol = database.get_index_type<asset_index>().indices().get<by_symbol>();
|
||||||
asset asset_to_issue = asset(swdo.peerplays_asset.amount * asset_price.quote.amount / asset_price.base.amount, database.get_global_properties().parameters.eth_asset());
|
const auto asset_itr = assets_by_symbol.find(swdo.sidechain_currency);
|
||||||
|
if (asset_itr == assets_by_symbol.end()) {
|
||||||
|
wlog("Could not find asset: ${symbol}", ("symbol", swdo.sidechain_currency));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const price asset_price = asset_itr->options.core_exchange_rate;
|
||||||
|
const asset asset_to_issue = asset(swdo.peerplays_asset.amount * asset_price.quote.amount / asset_price.base.amount, asset_itr->get_id());
|
||||||
|
|
||||||
proposal_create_operation proposal_op;
|
proposal_create_operation proposal_op;
|
||||||
proposal_op.fee_paying_account = plugin.get_current_son_object(sidechain).son_account;
|
proposal_op.fee_paying_account = plugin.get_current_son_object(sidechain).son_account;
|
||||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
const uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||||
|
|
||||||
son_wallet_deposit_process_operation swdp_op;
|
son_wallet_deposit_process_operation swdp_op;
|
||||||
|
|
@ -537,7 +580,7 @@ bool sidechain_net_handler_ethereum::process_withdrawal(const son_wallet_withdra
|
||||||
|
|
||||||
proposal_create_operation proposal_op;
|
proposal_create_operation proposal_op;
|
||||||
proposal_op.fee_paying_account = plugin.get_current_son_object(sidechain).son_account;
|
proposal_op.fee_paying_account = plugin.get_current_son_object(sidechain).son_account;
|
||||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
const uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||||
|
|
||||||
son_wallet_withdraw_process_operation swwp_op;
|
son_wallet_withdraw_process_operation swwp_op;
|
||||||
|
|
@ -683,7 +726,13 @@ bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechai
|
||||||
|
|
||||||
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
||||||
auto swwo = database.get<son_wallet_withdraw_object>(sto.object_id);
|
auto swwo = database.get<son_wallet_withdraw_object>(sto.object_id);
|
||||||
settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.eth_asset());
|
const auto &assets_by_symbol = database.get_index_type<asset_index>().indices().get<by_symbol>();
|
||||||
|
const auto asset_itr = assets_by_symbol.find(swwo.withdraw_currency);
|
||||||
|
if (asset_itr == assets_by_symbol.end()) {
|
||||||
|
wlog("Could not find asset: ${symbol}", ("symbol", swwo.withdraw_currency));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
settle_amount = asset(swwo.withdraw_amount, asset_itr->get_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -712,13 +761,6 @@ optional<asset> sidechain_net_handler_ethereum::estimate_withdrawal_transaction_
|
||||||
return optional<asset>{};
|
return optional<asset>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &assets_by_symbol = database.get_index_type<asset_index>().indices().get<by_symbol>();
|
|
||||||
auto asset_itr = assets_by_symbol.find("ETH");
|
|
||||||
if (asset_itr == assets_by_symbol.end()) {
|
|
||||||
wlog("Could not find asset matching ETH");
|
|
||||||
return optional<asset>{};
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &public_key = son->sidechain_public_keys.at(sidechain);
|
const auto &public_key = son->sidechain_public_keys.at(sidechain);
|
||||||
const auto data = ethereum::withdrawal_encoder::encode(public_key, 1 * 10000000000, son_wallet_withdraw_id_type{0}.operator object_id_type().operator std::string());
|
const auto data = ethereum::withdrawal_encoder::encode(public_key, 1 * 10000000000, son_wallet_withdraw_id_type{0}.operator object_id_type().operator std::string());
|
||||||
const std::string params = "[{\"from\":\"" + ethereum::add_0x(public_key) + "\", \"to\":\"" + wallet_contract_address + "\", \"data\":\"" + data + "\"}]";
|
const std::string params = "[{\"from\":\"" + ethereum::add_0x(public_key) + "\", \"to\":\"" + wallet_contract_address + "\", \"data\":\"" + data + "\"}]";
|
||||||
|
|
@ -726,7 +768,9 @@ optional<asset> sidechain_net_handler_ethereum::estimate_withdrawal_transaction_
|
||||||
const auto estimate_gas = ethereum::from_hex<int64_t>(rpc_client->get_estimate_gas(params));
|
const auto estimate_gas = ethereum::from_hex<int64_t>(rpc_client->get_estimate_gas(params));
|
||||||
const auto gas_price = ethereum::from_hex<int64_t>(rpc_client->get_gas_price());
|
const auto gas_price = ethereum::from_hex<int64_t>(rpc_client->get_gas_price());
|
||||||
const auto eth_gas_fee = double(estimate_gas * gas_price) / double{1000000000000000000};
|
const auto eth_gas_fee = double(estimate_gas * gas_price) / double{1000000000000000000};
|
||||||
return asset_itr->amount_from_string(std::to_string(eth_gas_fee));
|
|
||||||
|
const auto asset = database.get<asset_object>(database.get_global_properties().parameters.eth_asset());
|
||||||
|
return asset.amount_from_string(std::to_string(eth_gas_fee));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(const std::vector<son_info> &son_pubkeys, const std::string &object_id) {
|
std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(const std::vector<son_info> &son_pubkeys, const std::string &object_id) {
|
||||||
|
|
@ -739,12 +783,19 @@ std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(co
|
||||||
return ethereum::update_owners_encoder::encode(owners_weights, object_id);
|
return ethereum::update_owners_encoder::encode(owners_weights, object_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son_wallet_deposit_object &swdo) {
|
|
||||||
return "Deposit-Transaction";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string sidechain_net_handler_ethereum::create_withdrawal_transaction(const son_wallet_withdraw_object &swwo) {
|
std::string sidechain_net_handler_ethereum::create_withdrawal_transaction(const son_wallet_withdraw_object &swwo) {
|
||||||
return ethereum::withdrawal_encoder::encode(swwo.withdraw_address.substr(2), swwo.withdraw_amount.value * 10000000000, swwo.id.operator std::string());
|
if (swwo.withdraw_currency == "ETH") {
|
||||||
|
return ethereum::withdrawal_encoder::encode(ethereum::remove_0x(swwo.withdraw_address), swwo.withdraw_amount.value * 10000000000, swwo.id.operator std::string());
|
||||||
|
} else {
|
||||||
|
const auto it = erc20_addresses.left.find(swwo.withdraw_currency);
|
||||||
|
if (it == erc20_addresses.left.end()) {
|
||||||
|
elog("No erc-20 token: ${symbol}", ("symbol", swwo.withdraw_currency));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return ethereum::withdrawal_erc20_encoder::encode(ethereum::remove_0x(it->second), ethereum::remove_0x(swwo.withdraw_address), swwo.withdraw_amount.value, swwo.id.operator std::string());
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_transaction_object &sto) {
|
std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_transaction_object &sto) {
|
||||||
|
|
@ -761,10 +812,10 @@ std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_tra
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_ethereum::schedule_ethereum_listener() {
|
void sidechain_net_handler_ethereum::schedule_ethereum_listener() {
|
||||||
fc::time_point now = fc::time_point::now();
|
const fc::time_point now = fc::time_point::now();
|
||||||
int64_t time_to_next = 5000;
|
const int64_t time_to_next = 5000;
|
||||||
|
|
||||||
fc::time_point next_wakeup(now + fc::milliseconds(time_to_next));
|
const fc::time_point next_wakeup(now + fc::milliseconds(time_to_next));
|
||||||
|
|
||||||
_listener_task = fc::schedule([this] {
|
_listener_task = fc::schedule([this] {
|
||||||
ethereum_listener_loop();
|
ethereum_listener_loop();
|
||||||
|
|
@ -776,10 +827,9 @@ void sidechain_net_handler_ethereum::ethereum_listener_loop() {
|
||||||
schedule_ethereum_listener();
|
schedule_ethereum_listener();
|
||||||
|
|
||||||
const auto reply = rpc_client->eth_blockNumber();
|
const auto reply = rpc_client->eth_blockNumber();
|
||||||
//std::string reply = rpc_client->eth_get_logs(wallet_contract_address);
|
|
||||||
|
|
||||||
if (!reply.empty()) {
|
if (!reply.empty()) {
|
||||||
uint64_t head_block_number = ethereum::from_hex<uint64_t>(reply);
|
const uint64_t head_block_number = ethereum::from_hex<uint64_t>(reply);
|
||||||
|
|
||||||
if (head_block_number != last_block_received) {
|
if (head_block_number != last_block_received) {
|
||||||
//! Check that current block number is greater than last one
|
//! Check that current block number is greater than last one
|
||||||
|
|
@ -814,11 +864,11 @@ void sidechain_net_handler_ethereum::handle_event(const std::string &block_numbe
|
||||||
|
|
||||||
size_t tx_idx = -1;
|
size_t tx_idx = -1;
|
||||||
for (const auto &tx_child : block_json.get_child("result.transactions")) {
|
for (const auto &tx_child : block_json.get_child("result.transactions")) {
|
||||||
boost::property_tree::ptree tx = tx_child.second;
|
const boost::property_tree::ptree tx = tx_child.second;
|
||||||
tx_idx = tx_idx + 1;
|
tx_idx = tx_idx + 1;
|
||||||
|
|
||||||
std::string from = tx.get<std::string>("from");
|
const std::string from = tx.get<std::string>("from");
|
||||||
std::string to = tx.get<std::string>("to");
|
const std::string to = tx.get<std::string>("to");
|
||||||
|
|
||||||
std::string cmp_to = to;
|
std::string cmp_to = to;
|
||||||
std::transform(cmp_to.begin(), cmp_to.end(), cmp_to.begin(), ::toupper);
|
std::transform(cmp_to.begin(), cmp_to.end(), cmp_to.begin(), ::toupper);
|
||||||
|
|
@ -827,10 +877,35 @@ void sidechain_net_handler_ethereum::handle_event(const std::string &block_numbe
|
||||||
|
|
||||||
if (cmp_to == cmp_wallet_contract_address) {
|
if (cmp_to == cmp_wallet_contract_address) {
|
||||||
|
|
||||||
std::string value_s = tx.get<std::string>("value");
|
//! Check whether it is ERC-20 token deposit
|
||||||
boost::multiprecision::uint256_t amount(value_s);
|
std::string symbol;
|
||||||
amount = amount / 100000;
|
boost::multiprecision::uint256_t amount;
|
||||||
amount = amount / 100000;
|
const auto deposit_erc_20 = ethereum::deposit_erc20_decoder::decode(tx.get<std::string>("input"));
|
||||||
|
if (deposit_erc_20.valid()) {
|
||||||
|
std::string cmp_token = deposit_erc_20->token;
|
||||||
|
std::transform(cmp_token.begin(), cmp_token.end(), cmp_token.begin(), ::tolower);
|
||||||
|
|
||||||
|
const auto it = erc20_addresses.right.find(cmp_token);
|
||||||
|
if (it == erc20_addresses.right.end()) {
|
||||||
|
wlog("No erc-20 token with address: ${address}", ("address", cmp_token));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
symbol = it->second;
|
||||||
|
amount = deposit_erc_20->amount;
|
||||||
|
} else {
|
||||||
|
symbol = "ETH";
|
||||||
|
const std::string value_s = tx.get<std::string>("value");
|
||||||
|
amount = boost::multiprecision::uint256_t{value_s};
|
||||||
|
amount = amount / 100000;
|
||||||
|
amount = amount / 100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &assets_by_symbol = database.get_index_type<asset_index>().indices().get<by_symbol>();
|
||||||
|
const auto asset_itr = assets_by_symbol.find(symbol);
|
||||||
|
if (asset_itr == assets_by_symbol.end()) {
|
||||||
|
wlog("Could not find asset: ${symbol}", ("symbol", symbol));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
||||||
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum()));
|
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum()));
|
||||||
|
|
@ -841,22 +916,22 @@ void sidechain_net_handler_ethereum::handle_event(const std::string &block_numbe
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "ethereum"
|
ss << "ethereum"
|
||||||
<< "-" << tx.get<std::string>("hash") << "-" << tx_idx;
|
<< "-" << tx.get<std::string>("hash") << "-" << tx_idx;
|
||||||
std::string sidechain_uid = ss.str();
|
|
||||||
|
|
||||||
sidechain_event_data sed;
|
sidechain_event_data sed;
|
||||||
sed.timestamp = database.head_block_time();
|
sed.timestamp = database.head_block_time();
|
||||||
sed.block_num = database.head_block_num();
|
sed.block_num = database.head_block_num();
|
||||||
sed.sidechain = sidechain;
|
sed.sidechain = sidechain;
|
||||||
sed.sidechain_uid = sidechain_uid;
|
sed.type = sidechain_event_type::deposit;
|
||||||
|
sed.sidechain_uid = ss.str();
|
||||||
sed.sidechain_transaction_id = tx.get<std::string>("hash");
|
sed.sidechain_transaction_id = tx.get<std::string>("hash");
|
||||||
sed.sidechain_from = from;
|
sed.sidechain_from = from;
|
||||||
sed.sidechain_to = to;
|
sed.sidechain_to = to;
|
||||||
sed.sidechain_currency = "ETH";
|
sed.sidechain_currency = symbol;
|
||||||
sed.sidechain_amount = amount;
|
sed.sidechain_amount = amount;
|
||||||
sed.peerplays_from = addr_itr->sidechain_address_account;
|
sed.peerplays_from = addr_itr->sidechain_address_account;
|
||||||
sed.peerplays_to = database.get_global_properties().parameters.son_account();
|
sed.peerplays_to = database.get_global_properties().parameters.son_account();
|
||||||
price eth_price = database.get<asset_object>(database.get_global_properties().parameters.eth_asset()).options.core_exchange_rate;
|
const price price = asset_itr->options.core_exchange_rate;
|
||||||
sed.peerplays_asset = asset(sed.sidechain_amount * eth_price.base.amount / eth_price.quote.amount);
|
sed.peerplays_asset = asset(sed.sidechain_amount * price.base.amount / price.quote.amount);
|
||||||
|
|
||||||
add_to_son_listener_log("TRX : " + sed.sidechain_transaction_id);
|
add_to_son_listener_log("TRX : " + sed.sidechain_transaction_id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -950,6 +950,7 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) {
|
||||||
sed.timestamp = database.head_block_time();
|
sed.timestamp = database.head_block_time();
|
||||||
sed.block_num = database.head_block_num();
|
sed.block_num = database.head_block_num();
|
||||||
sed.sidechain = sidechain;
|
sed.sidechain = sidechain;
|
||||||
|
sed.type = sidechain_event_type::deposit;
|
||||||
sed.sidechain_uid = sidechain_uid;
|
sed.sidechain_uid = sidechain_uid;
|
||||||
sed.sidechain_transaction_id = transaction_id;
|
sed.sidechain_transaction_id = transaction_id;
|
||||||
sed.sidechain_from = from;
|
sed.sidechain_from = from;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <fc/crypto/hex.hpp>
|
#include <fc/crypto/hex.hpp>
|
||||||
#include <graphene/peerplays_sidechain/ethereum/encoders.hpp>
|
#include <graphene/peerplays_sidechain/ethereum/encoders.hpp>
|
||||||
|
#include <graphene/peerplays_sidechain/ethereum/decoders.hpp>
|
||||||
#include <graphene/peerplays_sidechain/ethereum/transaction.hpp>
|
#include <graphene/peerplays_sidechain/ethereum/transaction.hpp>
|
||||||
|
|
||||||
using namespace graphene::peerplays_sidechain::ethereum;
|
using namespace graphene::peerplays_sidechain::ethereum;
|
||||||
|
|
@ -9,22 +10,43 @@ using namespace graphene::peerplays_sidechain::ethereum;
|
||||||
BOOST_AUTO_TEST_SUITE(ethereum_transaction_tests)
|
BOOST_AUTO_TEST_SUITE(ethereum_transaction_tests)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(withdrawal_encoder_test) {
|
BOOST_AUTO_TEST_CASE(withdrawal_encoder_test) {
|
||||||
const auto tx = withdrawal_encoder::encode("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", 10000000000, "1.36.0");
|
const auto tx = withdrawal_encoder::encode("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", 10000000000, "1.39.0");
|
||||||
BOOST_CHECK_EQUAL(tx, "0xe088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33362E300000000000000000000000000000000000000000000000000000");
|
BOOST_CHECK_EQUAL(tx, "0xe088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33392E300000000000000000000000000000000000000000000000000000");
|
||||||
|
|
||||||
const auto tx1 = withdrawal_encoder::encode("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", 10000000000, "1.36.1");
|
const auto tx1 = withdrawal_encoder::encode("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", 10000000000, "1.39.1");
|
||||||
BOOST_CHECK_EQUAL(tx1, "0xe088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33362E310000000000000000000000000000000000000000000000000000");
|
BOOST_CHECK_EQUAL(tx1, "0xe088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33392E310000000000000000000000000000000000000000000000000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(withdrawal_signature_encoder_test) {
|
BOOST_AUTO_TEST_CASE(withdrawal_signature_encoder_test) {
|
||||||
const signature_encoder encoder{withdrawal_function_signature};
|
|
||||||
|
|
||||||
encoded_sign_transaction transaction;
|
encoded_sign_transaction transaction;
|
||||||
transaction.data = "0xe088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33362E300000000000000000000000000000000000000000000000000000";
|
transaction.data = "0xe088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33392E300000000000000000000000000000000000000000000000000000";
|
||||||
transaction.sign = sign_hash(keccak_hash(transaction.data), "0x21", "eb5749a569e6141a3b08249d4a0d84f9ef22c67651ba29adb8eb6fd43fc83060" );
|
transaction.sign = sign_hash(keccak_hash(transaction.data), "0x21", "eb5749a569e6141a3b08249d4a0d84f9ef22c67651ba29adb8eb6fd43fc83060" );
|
||||||
|
|
||||||
|
const auto function_signature = signature_encoder::get_function_signature_from_transaction(transaction.data);
|
||||||
|
BOOST_REQUIRE_EQUAL(function_signature.empty(), false);
|
||||||
|
const signature_encoder encoder{function_signature};
|
||||||
const auto tx = encoder.encode({transaction});
|
const auto tx = encoder.encode({transaction});
|
||||||
BOOST_CHECK_EQUAL(tx, "0xdaac6c8100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000065c4622d2ff2b2d89c5c6f8225ab0f979bc69d4fcd4fd47db757b66fb8a39e2bc5522be5d101aa11e66da78db973f136b323be10bd107ff0b648f06b4c71ef2a4f00000000000000000000000000000000000000000000000000000000000000a4e088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33362E30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
BOOST_CHECK_EQUAL(tx, "0xdaac6c810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006689c3a93d7059430d19ff952900dfada310c0dcced9ed046c335f886091c7e50c1a01016a488777b41a1815ca01a7d809ed47c36dcb0d5f86a43b079ce0d04afe00000000000000000000000000000000000000000000000000000000000000a4e088747b0000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc1200000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312E33392E30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(withdrawal_erc20_encoder_test) {
|
||||||
|
const auto tx = withdrawal_erc20_encoder::encode("cc806da9df9d634b5dac0aa36dca1e7780e42C60", "5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", 10, "1.39.0");
|
||||||
|
BOOST_CHECK_EQUAL(tx, "0x483c0467000000000000000000000000cc806da9df9d634b5dac0aa36dca1e7780e42C600000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc12000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000006312E33392E300000000000000000000000000000000000000000000000000000");
|
||||||
|
|
||||||
|
const auto tx1 = withdrawal_erc20_encoder::encode("cc806da9df9d634b5dac0aa36dca1e7780e42C60", "5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", 10, "1.39.1");
|
||||||
|
BOOST_CHECK_EQUAL(tx1, "0x483c0467000000000000000000000000cc806da9df9d634b5dac0aa36dca1e7780e42C600000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc12000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000006312E33392E310000000000000000000000000000000000000000000000000000");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(withdrawal_erc20_signature_encoder_test) {
|
||||||
|
encoded_sign_transaction transaction;
|
||||||
|
transaction.data = "0x483c0467000000000000000000000000cc806da9df9d634b5dac0aa36dca1e7780e42C600000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc12000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000006312E33392E300000000000000000000000000000000000000000000000000000";
|
||||||
|
transaction.sign = sign_hash(keccak_hash(transaction.data), "0x21", "eb5749a569e6141a3b08249d4a0d84f9ef22c67651ba29adb8eb6fd43fc83060" );
|
||||||
|
|
||||||
|
const auto function_signature = signature_encoder::get_function_signature_from_transaction(transaction.data);
|
||||||
|
BOOST_REQUIRE_EQUAL(function_signature.empty(), false);
|
||||||
|
const signature_encoder encoder{function_signature};
|
||||||
|
const auto tx = encoder.encode({transaction});
|
||||||
|
BOOST_CHECK_EQUAL(tx, "0xd2bf286600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000066f51f7732435016936f0e21aa3c290023ea96ddbc369a957aca28a865cb5004a46675855fccd4bd5a283e1ff61aa60ca9b8b63664e770689e5cfc1a0c6bbdc79a00000000000000000000000000000000000000000000000000000000000000c4483c0467000000000000000000000000cc806da9df9d634b5dac0aa36dca1e7780e42C600000000000000000000000005fbbb31be52608d2f52247e8400b7fcaa9e0bc12000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000006312E33392E30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(update_owners_encoder_test) {
|
BOOST_AUTO_TEST_CASE(update_owners_encoder_test) {
|
||||||
|
|
@ -32,23 +54,36 @@ BOOST_AUTO_TEST_CASE(update_owners_encoder_test) {
|
||||||
owners_weights.emplace_back("5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12", 1);
|
owners_weights.emplace_back("5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12", 1);
|
||||||
owners_weights.emplace_back("76ce31bd03f601c3fc13732def921c5bac282676", 1);
|
owners_weights.emplace_back("76ce31bd03f601c3fc13732def921c5bac282676", 1);
|
||||||
|
|
||||||
const auto tx = update_owners_encoder::encode(owners_weights, "1.35.0");
|
const auto tx = update_owners_encoder::encode(owners_weights, "1.39.0");
|
||||||
BOOST_CHECK_EQUAL(tx, "0x23ab6adf000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac28267600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33352E300000000000000000000000000000000000000000000000000000");
|
BOOST_CHECK_EQUAL(tx, "0x23ab6adf000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac28267600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33392E300000000000000000000000000000000000000000000000000000");
|
||||||
|
|
||||||
owners_weights.emplace_back("09ee460834498a4ee361beb819470061b7381b49", 1);
|
owners_weights.emplace_back("09ee460834498a4ee361beb819470061b7381b49", 1);
|
||||||
const auto tx1 = update_owners_encoder::encode(owners_weights, "1.36.1");
|
const auto tx1 = update_owners_encoder::encode(owners_weights, "1.39.1");
|
||||||
BOOST_CHECK_EQUAL(tx1, "0x23ab6adf0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac282676000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009ee460834498a4ee361beb819470061b7381b4900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33362E310000000000000000000000000000000000000000000000000000");
|
BOOST_CHECK_EQUAL(tx1, "0x23ab6adf0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac282676000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009ee460834498a4ee361beb819470061b7381b4900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33392E310000000000000000000000000000000000000000000000000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(update_owners_signature_encoder_test) {
|
BOOST_AUTO_TEST_CASE(update_owners_signature_encoder_test) {
|
||||||
const signature_encoder encoder{update_owners_function_signature};
|
|
||||||
|
|
||||||
encoded_sign_transaction transaction;
|
encoded_sign_transaction transaction;
|
||||||
transaction.data = "0x23ab6adf000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac28267600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33352E300000000000000000000000000000000000000000000000000000";
|
transaction.data = "0x23ab6adf000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac28267600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33392E300000000000000000000000000000000000000000000000000000";
|
||||||
transaction.sign = sign_hash(keccak_hash(transaction.data), "0x21", "eb5749a569e6141a3b08249d4a0d84f9ef22c67651ba29adb8eb6fd43fc83060" );
|
transaction.sign = sign_hash(keccak_hash(transaction.data), "0x21", "eb5749a569e6141a3b08249d4a0d84f9ef22c67651ba29adb8eb6fd43fc83060" );
|
||||||
|
|
||||||
|
const auto function_signature = signature_encoder::get_function_signature_from_transaction(transaction.data);
|
||||||
|
BOOST_REQUIRE_EQUAL(function_signature.empty(), false);
|
||||||
|
const signature_encoder encoder{function_signature};
|
||||||
const auto tx = encoder.encode({transaction});
|
const auto tx = encoder.encode({transaction});
|
||||||
BOOST_CHECK_EQUAL(tx, "0x9d6086730000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006698877eafa525c1a55f6b5e0a7187dfae484c97d9f77c4421a00276a9408a3e713d24402b44c05a883142fcffa84e1a802be37c17bb360f6f4810eb0415c8bbfd000000000000000000000000000000000000000000000000000000000000012423ab6adf000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac28267600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33352E30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
BOOST_CHECK_EQUAL(tx, "0x9d608673000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000667121da3c6ab5054b1a77cac477f24e7ce7bfcb5e3a857cfcaf48e67fc8f003ac38dfa8821525383608a68c9f215f9a2a232e192ae80079cd2f31b0e01caa6e1d000000000000000000000000000000000000000000000000000000000000012423ab6adf000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC12000000000000000000000000000000000000000000000000000000000000000100000000000000000000000076ce31bd03f601c3fc13732def921c5bac28267600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006312E33392E30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(deposit_erc20_decoder_test) {
|
||||||
|
const auto erc_20_1 = deposit_erc20_decoder::decode("0x97feb926000000000000000000000000cc806da9df9d634b5dac0aa36dca1e7780e42c600000000000000000000000000000000000000000000000000000000000000064");
|
||||||
|
BOOST_REQUIRE_EQUAL(erc_20_1.valid(), true);
|
||||||
|
BOOST_CHECK_EQUAL(erc_20_1->token, "0xcc806da9df9d634b5dac0aa36dca1e7780e42c60");
|
||||||
|
BOOST_CHECK_EQUAL(erc_20_1->amount, 100);
|
||||||
|
|
||||||
|
const auto erc_20_2 = deposit_erc20_decoder::decode("0x97feb926000000000000000000000000cc806da9df9d634b5dac0aa36dca1e7780e42c600000000000000000000000000000000000000000000000006400000000000000");
|
||||||
|
BOOST_REQUIRE_EQUAL(erc_20_2.valid(), true);
|
||||||
|
BOOST_CHECK_EQUAL(erc_20_2->token, "0xcc806da9df9d634b5dac0aa36dca1e7780e42c60");
|
||||||
|
BOOST_CHECK_EQUAL(erc_20_2->amount, 7205759403792793600);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(raw_transaction_serialization_test) {
|
BOOST_AUTO_TEST_CASE(raw_transaction_serialization_test) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue