remove hardcodes, implementation build_transaction safe_transaction_encoder

This commit is contained in:
Pavel Baykov 2022-06-15 09:16:55 -03:00
parent 647a5369fc
commit 6e213fcfad
2 changed files with 1139 additions and 1097 deletions

View file

@ -126,6 +126,13 @@ public:
private: private:
class ethereum_function_call_encoder { class ethereum_function_call_encoder {
public: public:
enum operation_t {
OPERATION_CALL,
OPERATION_DELEGATE_CALL
};
static constexpr const char*const default_prev_addr = "0000000000000000000000000000000000000001";
std::string encode_function_signature(const std::string& function_signature); std::string encode_function_signature(const std::string& function_signature);
std::string encode_address(const std::string& addr); std::string encode_address(const std::string& addr);
std::string encode_uint256(const std::string& value); std::string encode_uint256(const std::string& value);
@ -133,7 +140,23 @@ private:
std::string encode_bytes(const std::string& values); std::string encode_bytes(const std::string& values);
}; };
class safe_transaction_encoder {
public:
static constexpr const char*const default_safe_tx_gas = "0";
static constexpr const char*const default_data_gas = "0";
static constexpr const char*const default_gas_price = "0";
static constexpr const char*const default_gas_token = "0000000000000000000000000000000000000000";
static constexpr const char*const default_refund_receiver = "0000000000000000000000000000000000000000";
std::string create_safe_address(const std::vector<std::string> owner_addresses, uint32_t threshold);
std::string build_transaction(const std::string& safe_account_addr, const std::string& value, const std::string& data, uint8_t operation, const std::string& safeTxGas, const std::string& dataGas, const std::string& gasPrice, const std::string& gasToken, const std::string& refundReceiver);
private:
ethereum_function_call_encoder m_ethereum_function_call_encoder; ethereum_function_call_encoder m_ethereum_function_call_encoder;
};
ethereum_function_call_encoder m_ethereum_function_call_encoder;
safe_transaction_encoder m_safe_transaction_encoder;
std::shared_ptr<fc::thread> _thread; std::shared_ptr<fc::thread> _thread;
std::string signature; std::string signature;

View file

@ -44,8 +44,8 @@ std::string eth_rpc_client::ethereum_function_call_encoder::encode_function_sign
}; };
std::string eth_rpc_client::ethereum_function_call_encoder::encode_address(const std::string& addr) { std::string eth_rpc_client::ethereum_function_call_encoder::encode_address(const std::string& addr) {
FC_ASSERT(20 == addr.length()); FC_ASSERT(40 == addr.length());
std::string output = str(boost::format("%012u") % 0) + addr; std::string output = str(boost::format("%024u") % 0) + addr;
return output; return output;
} }
@ -66,6 +66,36 @@ std::string eth_rpc_client::ethereum_function_call_encoder::encode_bytes(const s
return output; return output;
} }
std::string eth_rpc_client::safe_transaction_encoder::create_safe_address(const std::vector<std::string> owner_addresses, uint32_t threshold) {
}
std::string eth_rpc_client::safe_transaction_encoder::build_transaction(const std::string& safe_account_addr, const std::string& value, const std::string& data, uint8_t operation, const std::string& safeTxGas, const std::string& dataGas, const std::string& gasPrice, const std::string& gasToken, const std::string& refundReceiver){
//execTransaction method of smart contract , using safe-account address
//execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures)
std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)");
FC_ASSERT("6a761202" == method_id);
//"<checksummed address>"
std::string to = m_ethereum_function_call_encoder.encode_address(safe_account_addr);
// Value in wei
std::string value_encoded = m_ethereum_function_call_encoder.encode_uint256(value);
// 0 CALL, 1 DELEGATE_CALL
std::string operation_encoded = m_ethereum_function_call_encoder.encode_uint8(operation);
// Max gas to use in the transaction
std::string safeTxGas_encoded = m_ethereum_function_call_encoder.encode_uint256(safeTxGas);
// Gas costs not related to the transaction execution (signature check, refund payment...)
std::string dataGas_encoded = m_ethereum_function_call_encoder.encode_uint256(dataGas);
// Gas price used for the refund calculation
std::string gasPrice_encoded = m_ethereum_function_call_encoder.encode_uint256(gasPrice);
//"<checksummed address>", Token address (hold by the Safe) to be used as a refund to the sender, if `null` is Ether
std::string gasToken_encoded = m_ethereum_function_call_encoder.encode_address(gasToken);
//"<checksummed address>", Address of receiver of gas payment (or `null` if tx.origin)
std::string refundReceiver_encoded = m_ethereum_function_call_encoder.encode_address(refundReceiver);
std::string message = method_id + to + value_encoded + data + operation_encoded + safeTxGas_encoded + dataGas_encoded + gasPrice_encoded + gasToken_encoded + refundReceiver_encoded;
return message;
}
eth_rpc_client::eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) : _thread(std::make_shared<fc::thread>("eth_rpc_client")){ eth_rpc_client::eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) : _thread(std::make_shared<fc::thread>("eth_rpc_client")){
geth_url = url; geth_url = url;
@ -282,7 +312,10 @@ uint64_t eth_rpc_client::eth_coinbase() {
} }
uint64_t eth_rpc_client::get_list_owners(const std::string& safe_account) { uint64_t eth_rpc_client::get_list_owners(const std::string& safe_account) {
return eth_call(safe_account.c_str(), "0xa0e67e2b"); //getOwners()
std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("getOwners()");
FC_ASSERT("a0e67e2b" == method_id);
return eth_call(safe_account.c_str(), method_id);
} }
uint64_t eth_rpc_client::add_owner(const std::string& addr ) { uint64_t eth_rpc_client::add_owner(const std::string& addr ) {
@ -290,22 +323,14 @@ uint64_t eth_rpc_client::add_owner(const std::string& addr ) {
FC_THROW_EXCEPTION(fc::exception, "Owners allready have addr: ${addr}", ("addr", addr)); FC_THROW_EXCEPTION(fc::exception, "Owners allready have addr: ${addr}", ("addr", addr));
} }
//It's require to execute
//execTransaction method of smart contract , using safe-account address
//execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures)
std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"); std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)");
FC_ASSERT("6a761202" == method_id); //addOwnerWithThreshold(address,uint256)
std::string address = safe_account_addr; std::string data_method_id = m_ethereum_function_call_encoder.encode_function_signature("addOwnerWithThreshold(address,uint256)");
std::string value = str(boost::format("%020u") % 0); FC_ASSERT("0d582f13" == data_method_id);
std::string data = "f8dc5dd9000000000000000000000000" + owners[0] + "000000000000000000000000" + addr + str(boost::format("%032u") % threshold); std::string data = data_method_id + m_ethereum_function_call_encoder.encode_address(addr) + m_ethereum_function_call_encoder.encode_uint256((boost::format("%x") % threshold).str());
std::string operation = "0";
std::string safeTxGas = str(boost::format("%032u") % 0); std::string message = m_safe_transaction_encoder.build_transaction(safe_account_addr, "0", data, ethereum_function_call_encoder::operation_t::OPERATION_CALL, m_safe_transaction_encoder.default_safe_tx_gas, m_safe_transaction_encoder.default_data_gas, m_safe_transaction_encoder.default_gas_price, m_safe_transaction_encoder.default_gas_token, m_safe_transaction_encoder.default_refund_receiver);
std::string dataGas = str(boost::format("%032u") % 0);
std::string gasPrice = str(boost::format("%032u") % 0);
std::string gasToken = "0000000000000000000000000000000000000000";
std::string refundReceiver = "0000000000000000000000000000000000000000";
std::string message = method_id + address + value + data + operation + safeTxGas + dataGas + gasPrice + gasToken + refundReceiver;
uint64_t id = eth_sign(account_address, message); uint64_t id = eth_sign(account_address, message);
m_requests[t_id] = req_t::ADD_OWNER; m_requests[t_id] = req_t::ADD_OWNER;
@ -322,20 +347,14 @@ uint64_t eth_rpc_client::remove_owner(const std::string& addr, uint32_t threshol
FC_THROW_EXCEPTION(fc::exception, "Owners size does not meet threshold: ${th}", ("th", threshold)); FC_THROW_EXCEPTION(fc::exception, "Owners size does not meet threshold: ${th}", ("th", threshold));
} }
//It's require to execute //removeOwner(address,address,uint256)
//execTransaction method of smart contract , using safe-account address std::string data_method_id = m_ethereum_function_call_encoder.encode_function_signature("removeOwner(address,address,uint256)");
//execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) FC_ASSERT("f8dc5dd9" == data_method_id);
std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"); std::string data = data_method_id + m_ethereum_function_call_encoder.encode_address(m_ethereum_function_call_encoder.default_prev_addr) + m_ethereum_function_call_encoder.encode_address(addr) + m_ethereum_function_call_encoder.encode_uint256((boost::format("%x") % threshold).str());
FC_ASSERT("6a761202" == method_id);
std::string address = safe_account_addr; std::string message = m_safe_transaction_encoder.build_transaction(safe_account_addr, "0", data, ethereum_function_call_encoder::operation_t::OPERATION_CALL, m_safe_transaction_encoder.default_safe_tx_gas, m_safe_transaction_encoder.default_data_gas, m_safe_transaction_encoder.default_gas_price, m_safe_transaction_encoder.default_gas_token, m_safe_transaction_encoder.default_refund_receiver);
std::string value = str(boost::format("%032u") % 0);
std::string data = "f8dc5dd90000000000000000000000000000000000000000000000000000000000000001000000000000000000000000" + addr + str(boost::format("%032u") % threshold); uint64_t id = eth_sign(account_address, message);
std::string operatio = "0";
std::string safeTxGas = str(boost::format("%032u") % 0);
std::string dataGas = str(boost::format("%032u") % 0);
std::string gasPrice = str(boost::format("%032u") % 0);
std::string gasToken = "0000000000000000000000000000000000000000";
std::string refundReceiver = "0000000000000000000000000000000000000000";
m_requests[t_id] = req_t::REMOVE_OWNER; m_requests[t_id] = req_t::REMOVE_OWNER;