Merged beatrice into 5050
This commit is contained in:
parent
75f16752d2
commit
26786d33a9
21 changed files with 1244 additions and 468 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -43,4 +43,4 @@ object_database/*
|
|||
*.pyo
|
||||
.vscode
|
||||
.DS_Store
|
||||
.idea
|
||||
.idea
|
||||
|
|
|
|||
|
|
@ -681,6 +681,20 @@ namespace graphene { namespace app {
|
|||
|
||||
crypto_api::crypto_api(){};
|
||||
|
||||
blind_signature crypto_api::blind_sign( const extended_private_key_type& key, const blinded_hash& hash, int i )
|
||||
{
|
||||
return fc::ecc::extended_private_key( key ).blind_sign( hash, i );
|
||||
}
|
||||
|
||||
signature_type crypto_api::unblind_signature( const extended_private_key_type& key,
|
||||
const extended_public_key_type& bob,
|
||||
const blind_signature& sig,
|
||||
const fc::sha256& hash,
|
||||
int i )
|
||||
{
|
||||
return fc::ecc::extended_private_key( key ).unblind_signature( extended_public_key( bob ), sig, hash, i );
|
||||
}
|
||||
|
||||
commitment_type crypto_api::blind( const blind_factor_type& blind, uint64_t value )
|
||||
{
|
||||
return fc::ecc::blind( blind, value );
|
||||
|
|
|
|||
|
|
@ -162,11 +162,10 @@ namespace detail {
|
|||
{
|
||||
// t.me/peerplays #seednodes
|
||||
vector<string> seeds = {
|
||||
// BEATRICE SEEDS:
|
||||
// "ppy-beatrice-seed.blckchnd.com:6666",
|
||||
// "159.69.223.206:7777",
|
||||
// "51.38.237.243:9666",
|
||||
// "pbsa-beatrice.blockchainprojectsbv.com:9195"
|
||||
"ppy-beatrice-seed.blckchnd.com:6666",
|
||||
"159.69.223.206:7777",
|
||||
"51.38.237.243:9666",
|
||||
"pbsa-beatrice.blockchainprojectsbv.com:9195"
|
||||
// OTTHER SEEDS:
|
||||
// "seed.ppy.blckchnd.com:6112", // blckchnd
|
||||
// "ppy.esteem.ws:7777", // good-karma
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
vector<bet_object> get_unmatched_bets_for_bettor(betting_market_id_type, account_id_type) const;
|
||||
vector<bet_object> get_all_unmatched_bets_for_bettor(account_id_type) const;
|
||||
|
||||
|
||||
// Lottery Assets
|
||||
vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
|
||||
unsigned limit = 100,
|
||||
|
|
|
|||
|
|
@ -737,7 +737,7 @@ FC_API(graphene::app::database_api,
|
|||
(list_betting_markets)
|
||||
(get_unmatched_bets_for_bettor)
|
||||
(get_all_unmatched_bets_for_bettor)
|
||||
|
||||
|
||||
// Sweeps
|
||||
(get_lotteries)
|
||||
(get_account_lotteries)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include <graphene/chain/betting_market_object.hpp>
|
||||
#include <graphene/chain/event_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <boost/integer/common_factor_rt.hpp>
|
||||
#include <boost/math/common_factor_rt.hpp>
|
||||
|
||||
#include <boost/msm/back/state_machine.hpp>
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#define DEFAULT_LOGGER "betting"
|
||||
#include <graphene/chain/betting_market_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <boost/integer/common_factor_rt.hpp>
|
||||
#include <boost/math/common_factor_rt.hpp>
|
||||
|
||||
#include <boost/msm/back/state_machine.hpp>
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
|
|
@ -101,7 +101,7 @@ share_type bet_object::get_exact_matching_amount() const
|
|||
|
||||
/* static */ std::pair<share_type, share_type> bet_object::get_ratio(bet_multiplier_type backer_multiplier)
|
||||
{
|
||||
share_type gcd = boost::integer::gcd(GRAPHENE_BETTING_ODDS_PRECISION, static_cast<int32_t>(backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION));
|
||||
share_type gcd = boost::math::gcd<bet_multiplier_type>(GRAPHENE_BETTING_ODDS_PRECISION, backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
return std::make_pair(GRAPHENE_BETTING_ODDS_PRECISION / gcd, (backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION) / gcd);
|
||||
}
|
||||
|
||||
|
|
@ -112,13 +112,13 @@ std::pair<share_type, share_type> bet_object::get_ratio() const
|
|||
|
||||
share_type bet_object::get_minimum_matchable_amount() const
|
||||
{
|
||||
share_type gcd = boost::integer::gcd(GRAPHENE_BETTING_ODDS_PRECISION, static_cast<int32_t>(backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION));
|
||||
share_type gcd = boost::math::gcd<bet_multiplier_type>(GRAPHENE_BETTING_ODDS_PRECISION, backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
return (back_or_lay == bet_type::back ? GRAPHENE_BETTING_ODDS_PRECISION : backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION) / gcd;
|
||||
}
|
||||
|
||||
share_type bet_object::get_minimum_matching_amount() const
|
||||
{
|
||||
share_type gcd = boost::integer::gcd(GRAPHENE_BETTING_ODDS_PRECISION, static_cast<int32_t>(backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION));
|
||||
share_type gcd = boost::math::gcd<bet_multiplier_type>(GRAPHENE_BETTING_ODDS_PRECISION, backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
return (back_or_lay == bet_type::lay ? GRAPHENE_BETTING_ODDS_PRECISION : backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION) / gcd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
void_result do_evaluate( const asset_create_operation& o );
|
||||
object_id_type do_apply( const asset_create_operation& o );
|
||||
|
||||
// copied from bitshares. (https://github.com/bitshares/bitshares-core/issues/429)
|
||||
|
||||
/** override the default behavior defined by generic_evalautor which is to
|
||||
* post the fee to fee_paying_account_stats.pending_fees
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <graphene/db/generic_index.hpp>
|
||||
#include <graphene/chain/protocol/event.hpp>
|
||||
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
class event_object;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
namespace graphene { namespace chain { struct fee_schedule; } }
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
struct parameter_extension
|
||||
struct bet_parameter_extension
|
||||
{
|
||||
optional< bet_multiplier_type > min_bet_multiplier;
|
||||
optional< bet_multiplier_type > max_bet_multiplier;
|
||||
|
|
@ -44,7 +44,9 @@ namespace graphene { namespace chain {
|
|||
asset_id_type sweeps_distribution_asset = SWEEPS_DEFAULT_DISTRIBUTION_ASSET;
|
||||
account_id_type sweeps_vesting_accumulator_account = SWEEPS_ACCUMULATOR_ACCOUNT;
|
||||
};
|
||||
typedef static_variant<void_t,sweeps_parameters_extension> parameter_extension;
|
||||
|
||||
typedef static_variant<void_t,sweeps_parameters_extension,bet_parameter_extension> parameter_extension;
|
||||
|
||||
struct chain_parameters
|
||||
{
|
||||
/** using a smart ref breaks the circular dependency created between operations and the fee schedule */
|
||||
|
|
@ -120,7 +122,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::parameter_extension,
|
||||
FC_REFLECT( graphene::chain::bet_parameter_extension,
|
||||
(min_bet_multiplier)
|
||||
(max_bet_multiplier)
|
||||
(betting_rake_fee_percentage)
|
||||
|
|
|
|||
28
libraries/deterministic_openssl_rand/CMakeLists.txt
Normal file
28
libraries/deterministic_openssl_rand/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
file(GLOB headers "include/graphene/utilities/*.hpp")
|
||||
|
||||
set(sources deterministic_openssl_rand.cpp
|
||||
${headers})
|
||||
|
||||
add_library( deterministic_openssl_rand
|
||||
${sources}
|
||||
${HEADERS} )
|
||||
target_link_libraries( deterministic_openssl_rand fc )
|
||||
target_include_directories( deterministic_openssl_rand
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../blockchain/include"
|
||||
)
|
||||
|
||||
if (USE_PCH)
|
||||
set_target_properties(deterministic_openssl_rand PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
|
||||
cotire(deterministic_openssl_rand)
|
||||
endif(USE_PCH)
|
||||
|
||||
install( TARGETS
|
||||
deterministic_openssl_rand
|
||||
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
install( FILES ${headers} DESTINATION "include/graphene/deterministic_openssl_rand" )
|
||||
|
|
@ -2063,6 +2063,5 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(get_binned_order_book)
|
||||
(get_matched_bets_for_bettor)
|
||||
(get_all_matched_bets_for_bettor)
|
||||
|
||||
(buy_ticket)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -128,6 +128,17 @@ int main(int argc, char** argv) {
|
|||
std::cout << app_options << "\n";
|
||||
return 0;
|
||||
}
|
||||
if (options.count("version"))
|
||||
{
|
||||
std::string witness_version(graphene::utilities::git_revision_description);
|
||||
const size_t pos = witness_version.find('/');
|
||||
if( pos != std::string::npos && witness_version.size() > pos )
|
||||
witness_version = witness_version.substr( pos + 1 );
|
||||
std::cerr << "Version: " << witness_version << "\n";
|
||||
std::cerr << "Git Revision: " << graphene::utilities::git_revision_sha << "\n";
|
||||
std::cerr << "Built: " << __DATE__ " at " __TIME__ << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
fc::path data_dir;
|
||||
if( options.count("data-dir") )
|
||||
|
|
@ -193,3 +204,109 @@ int main(int argc, char** argv) {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// logging config is too complicated to be parsed by boost::program_options,
|
||||
// so we do it by hand
|
||||
//
|
||||
// Currently, you can only specify the filenames and logging levels, which
|
||||
// are all most users would want to change. At a later time, options can
|
||||
// be added to control rotation intervals, compression, and other seldom-
|
||||
// used features
|
||||
void write_default_logging_config_to_stream(std::ostream& out)
|
||||
{
|
||||
out << "# declare an appender named \"stderr\" that writes messages to the console\n"
|
||||
"[log.console_appender.stderr]\n"
|
||||
"stream=std_error\n\n"
|
||||
"# declare an appender named \"p2p\" that writes messages to p2p.log\n"
|
||||
"[log.file_appender.p2p]\n"
|
||||
"filename=logs/p2p/p2p.log\n"
|
||||
"# filename can be absolute or relative to this config file\n\n"
|
||||
"# route any messages logged to the default logger to the \"stderr\" logger we\n"
|
||||
"# declared above, if they are info level are higher\n"
|
||||
"[logger.default]\n"
|
||||
"level=info\n"
|
||||
"appenders=stderr\n\n"
|
||||
"# route messages sent to the \"p2p\" logger to the p2p appender declared above\n"
|
||||
"[logger.p2p]\n"
|
||||
"level=info\n"
|
||||
"appenders=p2p\n\n";
|
||||
}
|
||||
|
||||
fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::path& config_ini_filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
fc::logging_config logging_config;
|
||||
bool found_logging_config = false;
|
||||
|
||||
boost::property_tree::ptree config_ini_tree;
|
||||
boost::property_tree::ini_parser::read_ini(config_ini_filename.preferred_string().c_str(), config_ini_tree);
|
||||
for (const auto& section : config_ini_tree)
|
||||
{
|
||||
const std::string& section_name = section.first;
|
||||
const boost::property_tree::ptree& section_tree = section.second;
|
||||
|
||||
const std::string console_appender_section_prefix = "log.console_appender.";
|
||||
const std::string file_appender_section_prefix = "log.file_appender.";
|
||||
const std::string logger_section_prefix = "logger.";
|
||||
|
||||
if (boost::starts_with(section_name, console_appender_section_prefix))
|
||||
{
|
||||
std::string console_appender_name = section_name.substr(console_appender_section_prefix.length());
|
||||
std::string stream_name = section_tree.get<std::string>("stream");
|
||||
|
||||
// construct a default console appender config here
|
||||
// stdout/stderr will be taken from ini file, everything else hard-coded here
|
||||
fc::console_appender::config console_appender_config;
|
||||
console_appender_config.level_colors.emplace_back(
|
||||
fc::console_appender::level_color(fc::log_level::debug,
|
||||
fc::console_appender::color::green));
|
||||
console_appender_config.level_colors.emplace_back(
|
||||
fc::console_appender::level_color(fc::log_level::warn,
|
||||
fc::console_appender::color::brown));
|
||||
console_appender_config.level_colors.emplace_back(
|
||||
fc::console_appender::level_color(fc::log_level::error,
|
||||
fc::console_appender::color::cyan));
|
||||
console_appender_config.stream = fc::variant(stream_name).as<fc::console_appender::stream::type>();
|
||||
logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config)));
|
||||
found_logging_config = true;
|
||||
}
|
||||
else if (boost::starts_with(section_name, file_appender_section_prefix))
|
||||
{
|
||||
std::string file_appender_name = section_name.substr(file_appender_section_prefix.length());
|
||||
fc::path file_name = section_tree.get<std::string>("filename");
|
||||
if (file_name.is_relative())
|
||||
file_name = fc::absolute(config_ini_filename).parent_path() / file_name;
|
||||
|
||||
|
||||
// construct a default file appender config here
|
||||
// filename will be taken from ini file, everything else hard-coded here
|
||||
fc::file_appender::config file_appender_config;
|
||||
file_appender_config.filename = file_name;
|
||||
file_appender_config.flush = true;
|
||||
file_appender_config.rotate = true;
|
||||
file_appender_config.rotation_interval = fc::hours(1);
|
||||
file_appender_config.rotation_limit = fc::days(1);
|
||||
logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config)));
|
||||
found_logging_config = true;
|
||||
}
|
||||
else if (boost::starts_with(section_name, logger_section_prefix))
|
||||
{
|
||||
std::string logger_name = section_name.substr(logger_section_prefix.length());
|
||||
std::string level_string = section_tree.get<std::string>("level");
|
||||
std::string appenders_string = section_tree.get<std::string>("appenders");
|
||||
fc::logger_config logger_config(logger_name);
|
||||
logger_config.level = fc::variant(level_string).as<fc::log_level>();
|
||||
boost::split(logger_config.appenders, appenders_string,
|
||||
boost::is_any_of(" ,"),
|
||||
boost::token_compress_on);
|
||||
logging_config.loggers.push_back(logger_config);
|
||||
found_logging_config = true;
|
||||
}
|
||||
}
|
||||
if (found_logging_config)
|
||||
return logging_config;
|
||||
else
|
||||
return fc::optional<fc::logging_config>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -377,41 +377,49 @@ BOOST_AUTO_TEST_CASE(binned_order_books)
|
|||
|
||||
// place lay bets at decimal odds of 1.55, 1.6, 1.65, 1.66, and 1.67
|
||||
// these bets will get rounded down, actual amounts are 99, 99, 91, 99, and 67
|
||||
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
//
|
||||
// binned_orders_point_one = bookie_api.get_binned_order_book(capitals_win_market.id, 1);
|
||||
// idump((binned_orders_point_one));
|
||||
//
|
||||
// // the binned orders returned should be chosen so that we if we assume those orders are real and we place
|
||||
// // matching lay orders, we will completely consume the underlying orders and leave no orders on the books
|
||||
// //
|
||||
// // for the bets bob placed above, we shoudl get 356 @ 1.6, 99 @ 1.5
|
||||
// BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_back_bets.size(), 0u);
|
||||
// BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_lay_bets.size(), 2u);
|
||||
// for (const graphene::bookie::order_bin& binned_order : binned_orders_point_one.aggregated_lay_bets)
|
||||
// {
|
||||
// // compute the matching lay order
|
||||
// share_type back_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::lay, true /* round up */);
|
||||
// ilog("Alice is backing with ${back_amount} at odds ${odds} to match the binned lay amount ${lay_amount}", ("back_amount", back_amount)("odds", binned_order.backer_multiplier)("lay_amount", binned_order.amount_to_bet));
|
||||
// place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(back_amount, asset_id_type()), binned_order.backer_multiplier);
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
|
||||
// while (bet_iter != bet_odds_idx.end() &&
|
||||
// bet_iter->betting_market_id == capitals_win_market.id)
|
||||
// {
|
||||
// idump((*bet_iter));
|
||||
// ++bet_iter;
|
||||
// }
|
||||
//
|
||||
// BOOST_CHECK(bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id)) == bet_odds_idx.end());
|
||||
//
|
||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 16 * GRAPHENE_BETTING_ODDS_PRECISION / 10);
|
||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 166 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 167 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||
|
||||
binned_orders_point_one = bookie_api.get_binned_order_book(capitals_win_market.id, 1);
|
||||
idump((binned_orders_point_one));
|
||||
|
||||
// the binned orders returned should be chosen so that we if we assume those orders are real and we place
|
||||
// matching lay orders, we will completely consume the underlying orders and leave no orders on the books
|
||||
//
|
||||
// for the bets bob placed above, we shoudl get 356 @ 1.6, 99 @ 1.5
|
||||
BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_back_bets.size(), 0u);
|
||||
BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_lay_bets.size(), 2u);
|
||||
for (const graphene::bookie::order_bin& binned_order : binned_orders_point_one.aggregated_lay_bets)
|
||||
{
|
||||
// compute the matching lay order
|
||||
share_type back_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::lay, true /* round up */);
|
||||
ilog("Alice is backing with ${back_amount} at odds ${odds} to match the binned lay amount ${lay_amount}", ("back_amount", back_amount)("odds", binned_order.backer_multiplier)("lay_amount", binned_order.amount_to_bet));
|
||||
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(back_amount, asset_id_type()), binned_order.backer_multiplier);
|
||||
|
||||
ilog("After alice's bet, order book is:");
|
||||
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
|
||||
while (bet_iter != bet_odds_idx.end() &&
|
||||
bet_iter->betting_market_id == capitals_win_market.id)
|
||||
{
|
||||
idump((*bet_iter));
|
||||
++bet_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
|
||||
while (bet_iter != bet_odds_idx.end() &&
|
||||
bet_iter->betting_market_id == capitals_win_market.id)
|
||||
{
|
||||
idump((*bet_iter));
|
||||
++bet_iter;
|
||||
}
|
||||
|
||||
BOOST_CHECK(bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id)) == bet_odds_idx.end());
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
|
|
@ -898,43 +906,42 @@ BOOST_AUTO_TEST_CASE(bet_reversal_test)
|
|||
FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
//This test case need some analysis and commneting out for the time being
|
||||
// BOOST_AUTO_TEST_CASE(bet_against_exposure_test)
|
||||
// {
|
||||
// // test whether we can bet our entire balance in one direction, have it match, then reverse our bet (while having zero balance)
|
||||
// try
|
||||
// {
|
||||
// generate_blocks(1);
|
||||
// ACTORS( (alice)(bob) );
|
||||
// CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
|
||||
//
|
||||
// transfer(account_id_type(), alice_id, asset(10000000));
|
||||
// transfer(account_id_type(), bob_id, asset(10000000));
|
||||
// int64_t alice_expected_balance = 10000000;
|
||||
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
// int64_t bob_expected_balance = 10000000;
|
||||
// BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
|
||||
//
|
||||
// // back with alice's entire balance
|
||||
// place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
// alice_expected_balance -= 10000000;
|
||||
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
//
|
||||
// // lay with bob's entire balance, which fully matches bob's bet
|
||||
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
// bob_expected_balance -= 10000000;
|
||||
// BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
|
||||
//
|
||||
// // reverse the bet
|
||||
// place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(20000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
//
|
||||
// // try to re-reverse it, but go too far
|
||||
// BOOST_CHECK_THROW( place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(30000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION), fc::exception);
|
||||
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
// }
|
||||
// FC_LOG_AND_RETHROW()
|
||||
// }
|
||||
BOOST_AUTO_TEST_CASE(bet_against_exposure_test)
|
||||
{
|
||||
// test whether we can bet our entire balance in one direction, have it match, then reverse our bet (while having zero balance)
|
||||
try
|
||||
{
|
||||
generate_blocks(1);
|
||||
ACTORS( (alice)(bob) );
|
||||
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
|
||||
|
||||
transfer(account_id_type(), alice_id, asset(10000000));
|
||||
transfer(account_id_type(), bob_id, asset(10000000));
|
||||
int64_t alice_expected_balance = 10000000;
|
||||
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
int64_t bob_expected_balance = 10000000;
|
||||
BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
|
||||
|
||||
// back with alice's entire balance
|
||||
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
alice_expected_balance -= 10000000;
|
||||
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
|
||||
// lay with bob's entire balance, which fully matches bob's bet
|
||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
bob_expected_balance -= 10000000;
|
||||
BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
|
||||
|
||||
// reverse the bet
|
||||
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(20000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
|
||||
// try to re-reverse it, but go too far
|
||||
BOOST_CHECK_THROW( place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(30000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION), fc::exception);
|
||||
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
|
||||
}
|
||||
FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(persistent_objects_test)
|
||||
{
|
||||
|
|
@ -1527,18 +1534,17 @@ BOOST_AUTO_TEST_CASE(sport_delete_test_not_proposal)
|
|||
} FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
// No need for the below test as it shows in failed test case list. Should enable when sports related changes applied
|
||||
// BOOST_AUTO_TEST_CASE(sport_delete_test_not_existed_sport)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
|
||||
//
|
||||
// delete_sport(ice_hockey.id);
|
||||
//
|
||||
// BOOST_CHECK_THROW(delete_sport(ice_hockey.id), fc::exception);
|
||||
// } FC_LOG_AND_RETHROW()
|
||||
// }
|
||||
BOOST_AUTO_TEST_CASE(sport_delete_test_not_existed_sport)
|
||||
{
|
||||
try
|
||||
{
|
||||
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
|
||||
|
||||
delete_sport(ice_hockey.id);
|
||||
|
||||
BOOST_CHECK_THROW(delete_sport(ice_hockey.id), fc::exception);
|
||||
} FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_group_update_test)
|
||||
{
|
||||
|
|
@ -2776,26 +2782,24 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture)
|
|||
update_event_group(nhl.id, fc::optional<object_id_type>(), name);
|
||||
update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>());
|
||||
update_event_group(nhl.id, sport_id, name);
|
||||
|
||||
//Disabling the below 4 TRY_EXPECT_THROW lines to not throw anything beacuse functioning as expected
|
||||
|
||||
|
||||
// trx_state->_is_proposed_trx
|
||||
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>(), true), fc::exception);
|
||||
// TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>(), true), fc::exception, "_is_proposed_trx");
|
||||
TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>(), true), fc::exception, "_is_proposed_trx");
|
||||
|
||||
// #! nothing to change
|
||||
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>()), fc::exception);
|
||||
//TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>()), fc::exception, "nothing to change");
|
||||
TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>()), fc::exception, "nothing to change");
|
||||
|
||||
// #! sport_id must refer to a sport_id_type
|
||||
sport_id = capitals_win_market.id;
|
||||
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception);
|
||||
//TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "sport_id must refer to a sport_id_type");
|
||||
TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "sport_id must refer to a sport_id_type");
|
||||
|
||||
// #! invalid sport specified
|
||||
sport_id = sport_id_type(13);
|
||||
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception);
|
||||
//TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "invalid sport specified");
|
||||
TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "invalid sport specified");
|
||||
|
||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||
|
||||
|
|
@ -2938,65 +2942,60 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test )
|
|||
// reworked check_transasction for duplicate
|
||||
// now should not through an exception when there are different events with the same betting_market_group
|
||||
// and or the same betting_market
|
||||
// Need to revisit the following test, commeting for time being******
|
||||
// BOOST_AUTO_TEST_CASE( check_transaction_for_duplicate_reworked_test )
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// std::vector<internationalized_string_type> names_vec(104);
|
||||
//
|
||||
// // create 104 pattern for first name
|
||||
// for( char co = 'A'; co <= 'D'; ++co ) {
|
||||
// for( char ci = 'A'; ci <= 'Z'; ++ci ) {
|
||||
// std::string first_name = std::to_string(co) + std::to_string(ci);
|
||||
// std::string second_name = first_name + first_name;
|
||||
// names_vec.push_back( {{ first_name, second_name }} );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// sport_id_type sport_id = create_sport( {{"SN","SPORT_NAME"}} ).id;
|
||||
//
|
||||
// event_group_id_type event_group_id = create_event_group( {{"EG", "EVENT_GROUP"}}, sport_id ).id;
|
||||
//
|
||||
// betting_market_rules_id_type betting_market_rules_id =
|
||||
// create_betting_market_rules( {{"EN", "Rules"}}, {{"EN", "Some rules"}} ).id;
|
||||
//
|
||||
// for( const auto& name : names_vec )
|
||||
// {
|
||||
// proposal_create_operation pcop = proposal_create_operation::committee_proposal(
|
||||
// db.get_global_properties().parameters,
|
||||
// db.head_block_time()
|
||||
// );
|
||||
// pcop.review_period_seconds.reset();
|
||||
// pcop.review_period_seconds = db.get_global_properties().parameters.committee_proposal_review_period * 2;
|
||||
//
|
||||
// event_create_operation evcop;
|
||||
// evcop.event_group_id = event_group_id;
|
||||
// evcop.name = name;
|
||||
// evcop.season = name;
|
||||
//
|
||||
// betting_market_group_create_operation bmgcop;
|
||||
// bmgcop.description = name;
|
||||
// bmgcop.event_id = object_id_type(relative_protocol_ids, 0, 0);
|
||||
// bmgcop.rules_id = betting_market_rules_id;
|
||||
// bmgcop.asset_id = asset_id_type();
|
||||
//
|
||||
// betting_market_create_operation bmcop;
|
||||
// bmcop.group_id = object_id_type(relative_protocol_ids, 0, 1);
|
||||
// bmcop.payout_condition.insert( internationalized_string_type::value_type( "CN", "CONDI_NAME" ) );
|
||||
//
|
||||
// pcop.proposed_ops.emplace_back( evcop );
|
||||
// pcop.proposed_ops.emplace_back( bmgcop );
|
||||
// pcop.proposed_ops.emplace_back( bmcop );
|
||||
//
|
||||
// signed_transaction trx;
|
||||
// set_expiration( db, trx );
|
||||
// trx.operations.push_back( pcop );
|
||||
//
|
||||
// process_operation_by_witnesses( pcop );
|
||||
// }
|
||||
// }FC_LOG_AND_RETHROW()
|
||||
// }
|
||||
BOOST_AUTO_TEST_CASE( check_transaction_for_duplicate_reworked_test )
|
||||
{
|
||||
std::vector<internationalized_string_type> names_vec(104);
|
||||
|
||||
// create 104 pattern for first name
|
||||
for( char co = 'A'; co <= 'D'; ++co ) {
|
||||
for( char ci = 'A'; ci <= 'Z'; ++ci ) {
|
||||
std::string first_name = std::to_string(co) + std::to_string(ci);
|
||||
std::string second_name = first_name + first_name;
|
||||
names_vec.push_back( {{ first_name, second_name }} );
|
||||
}
|
||||
}
|
||||
|
||||
sport_id_type sport_id = create_sport( {{"SN","SPORT_NAME"}} ).id;
|
||||
|
||||
event_group_id_type event_group_id = create_event_group( {{"EG", "EVENT_GROUP"}}, sport_id ).id;
|
||||
|
||||
betting_market_rules_id_type betting_market_rules_id =
|
||||
create_betting_market_rules( {{"EN", "Rules"}}, {{"EN", "Some rules"}} ).id;
|
||||
|
||||
for( const auto& name : names_vec )
|
||||
{
|
||||
proposal_create_operation pcop = proposal_create_operation::committee_proposal(
|
||||
db.get_global_properties().parameters,
|
||||
db.head_block_time()
|
||||
);
|
||||
pcop.review_period_seconds.reset();
|
||||
|
||||
event_create_operation evcop;
|
||||
evcop.event_group_id = event_group_id;
|
||||
evcop.name = name;
|
||||
evcop.season = name;
|
||||
|
||||
betting_market_group_create_operation bmgcop;
|
||||
bmgcop.description = name;
|
||||
bmgcop.event_id = object_id_type(relative_protocol_ids, 0, 0);
|
||||
bmgcop.rules_id = betting_market_rules_id;
|
||||
bmgcop.asset_id = asset_id_type();
|
||||
|
||||
betting_market_create_operation bmcop;
|
||||
bmcop.group_id = object_id_type(relative_protocol_ids, 0, 1);
|
||||
bmcop.payout_condition.insert( internationalized_string_type::value_type( "CN", "CONDI_NAME" ) );
|
||||
|
||||
pcop.proposed_ops.emplace_back( evcop );
|
||||
pcop.proposed_ops.emplace_back( bmgcop );
|
||||
pcop.proposed_ops.emplace_back( bmcop );
|
||||
|
||||
signed_transaction trx;
|
||||
set_expiration( db, trx );
|
||||
trx.operations.push_back( pcop );
|
||||
|
||||
process_operation_by_witnesses( pcop );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
|
|
|||
|
|
@ -89,9 +89,11 @@ database_fixture::database_fixture()
|
|||
|
||||
boost::program_options::variables_map options;
|
||||
|
||||
// genesis_state.initial_timestamp = time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
genesis_state.initial_timestamp = time_point_sec( (fc::time_point::now().sec_since_epoch() / GRAPHENE_DEFAULT_BLOCK_INTERVAL) * GRAPHENE_DEFAULT_BLOCK_INTERVAL );
|
||||
// genesis_state.initial_parameters.witness_schedule_algorithm = GRAPHENE_WITNESS_SHUFFLED_ALGORITHM;
|
||||
genesis_state.initial_timestamp = time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
//int back_to_the_past = 0;
|
||||
//back_to_the_past = 7 * 24 * 60 * 60; // week
|
||||
//genesis_state.initial_timestamp = time_point_sec( (fc::time_point::now().sec_since_epoch() - back_to_the_past) / GRAPHENE_DEFAULT_BLOCK_INTERVAL * GRAPHENE_DEFAULT_BLOCK_INTERVAL );
|
||||
genesis_state.initial_parameters.witness_schedule_algorithm = GRAPHENE_WITNESS_SHUFFLED_ALGORITHM;
|
||||
|
||||
genesis_state.initial_active_witnesses = 10;
|
||||
for( unsigned i = 0; i < genesis_state.initial_active_witnesses; ++i )
|
||||
|
|
@ -713,8 +715,7 @@ const witness_object& database_fixture::create_witness( const account_object& ow
|
|||
secret_hash_type::encoder enc;
|
||||
fc::raw::pack(enc, signing_private_key);
|
||||
fc::raw::pack(enc, secret_hash_type());
|
||||
op.initial_secret = enc.result();
|
||||
|
||||
op.initial_secret = secret_hash_type::hash(enc.result());
|
||||
trx.operations.push_back(op);
|
||||
trx.validate();
|
||||
processed_transaction ptx = db.push_transaction(trx, ~0);
|
||||
|
|
|
|||
|
|
@ -842,7 +842,7 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
|
|||
sign( trx, get_account("init7" ).active.get_keys().front(),init_account_priv_key);
|
||||
*/
|
||||
db.push_transaction(trx);
|
||||
// BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(db));
|
||||
BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(db));
|
||||
}
|
||||
BOOST_TEST_MESSAGE( "Verifying that the interval didn't change immediately" );
|
||||
|
||||
|
|
@ -863,12 +863,12 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
|
|||
generate_block(); // get the maintenance skip slots out of the way
|
||||
|
||||
BOOST_TEST_MESSAGE( "Verify that the new block interval is 1 second" );
|
||||
// BOOST_CHECK_EQUAL(db.get_global_properties().parameters.block_interval, 1);
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.block_interval, 1);
|
||||
past_time = db.head_block_time().sec_since_epoch();
|
||||
generate_block();
|
||||
// BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 1);
|
||||
BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 1);
|
||||
generate_block();
|
||||
// BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 2);
|
||||
BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 2);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( pop_block_twice, database_fixture )
|
||||
|
|
@ -1087,7 +1087,6 @@ BOOST_FIXTURE_TEST_CASE( rsf_missed_blocks, database_fixture )
|
|||
|
||||
// the test written in 2015 should be revised, currently it is not possible to push block to db2
|
||||
// without skip_witness_signature | skip_witness_schedule_check | skip_authority_check
|
||||
/*
|
||||
BOOST_FIXTURE_TEST_CASE( transaction_invalidated_in_cache, database_fixture )
|
||||
{
|
||||
try
|
||||
|
|
@ -1112,9 +1111,7 @@ BOOST_FIXTURE_TEST_CASE( transaction_invalidated_in_cache, database_fixture )
|
|||
while( db2.head_block_num() < db.head_block_num() )
|
||||
{
|
||||
optional< signed_block > b = db.fetch_block_by_number( db2.head_block_num()+1 );
|
||||
db2.push_block(*b, database::skip_witness_signature|
|
||||
database::skip_authority_check|
|
||||
database::skip_witness_schedule_check);
|
||||
db2.push_block(*b, database::skip_witness_signature);
|
||||
}
|
||||
BOOST_CHECK( db2.get( alice_id ).name == "alice" );
|
||||
BOOST_CHECK( db2.get( bob_id ).name == "bob" );
|
||||
|
|
@ -1238,7 +1235,6 @@ BOOST_FIXTURE_TEST_CASE( transaction_invalidated_in_cache, database_fixture )
|
|||
throw;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
BOOST_AUTO_TEST_CASE( genesis_reserve_ids )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -79,16 +79,17 @@ BOOST_AUTO_TEST_CASE( nonzero_fee_test )
|
|||
}
|
||||
}
|
||||
|
||||
// fails
|
||||
// BOOST_AUTO_TEST_CASE(asset_claim_fees_test)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// ACTORS((alice)(bob)(izzy)(jill));
|
||||
// // Izzy issues asset to Alice
|
||||
// // Jill issues asset to Bob
|
||||
// // Alice and Bob trade in the market and pay fees
|
||||
// // Verify that Izzy and Jill can claim the fees
|
||||
// assertion if "No asset in the trade is CORE." in market_evaluator.cpp
|
||||
#if 0
|
||||
BOOST_AUTO_TEST_CASE(asset_claim_fees_test)
|
||||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice)(bob)(izzy)(jill));
|
||||
// Izzy issues asset to Alice
|
||||
// Jill issues asset to Bob
|
||||
// Alice and Bob trade in the market and pay fees
|
||||
// Verify that Izzy and Jill can claim the fees
|
||||
|
||||
// const share_type core_prec = asset::scaled_precision( asset_id_type()(db).precision );
|
||||
|
||||
|
|
@ -203,16 +204,17 @@ BOOST_AUTO_TEST_CASE( nonzero_fee_test )
|
|||
// GRAPHENE_REQUIRE_THROW( claim_fees( izzy_id, izzy_satoshi ), fc::exception );
|
||||
// BOOST_CHECK( izzycoin.dynamic_asset_data_id(db).accumulated_fees == _izzy(0).amount );
|
||||
|
||||
// // can claim in multiple goes
|
||||
// claim_fees( jill_id, _jill(4) );
|
||||
// BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(2).amount );
|
||||
// GRAPHENE_REQUIRE_THROW( claim_fees( jill_id, _jill(2) + jill_satoshi ), fc::exception );
|
||||
// claim_fees( jill_id, _jill(2) );
|
||||
// BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(0).amount );
|
||||
// }
|
||||
// }
|
||||
// FC_LOG_AND_RETHROW()
|
||||
// }
|
||||
// can claim in multiple goes
|
||||
claim_fees( jill_id, _jill(4) );
|
||||
BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(2).amount );
|
||||
GRAPHENE_REQUIRE_THROW( claim_fees( jill_id, _jill(2) + jill_satoshi ), fc::exception );
|
||||
claim_fees( jill_id, _jill(2) );
|
||||
BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(0).amount );
|
||||
}
|
||||
}
|
||||
FC_LOG_AND_RETHROW()
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// cashback_test infrastructure //
|
||||
|
|
@ -266,313 +268,314 @@ struct actor_audit
|
|||
int64_t ref_pct = 0; // referrer percentage should be this
|
||||
};
|
||||
|
||||
// BOOST_AUTO_TEST_CASE( cashback_test )
|
||||
// { try {
|
||||
// /* Account Structure used in this test *
|
||||
// * *
|
||||
// * /-----------------\ /-------------------\ *
|
||||
// * | life (Lifetime) | | rog (Lifetime) | *
|
||||
// * \-----------------/ \-------------------/ *
|
||||
// * | Ref&Reg | Refers | Registers | Registers *
|
||||
// * | | 75 | 25 | *
|
||||
// * v v v | *
|
||||
// * /----------------\ /----------------\ | *
|
||||
// * | ann (Annual) | | dumy (basic) | | *
|
||||
// * \----------------/ \----------------/ |-------------. *
|
||||
// * 80 | Refers L--------------------------------. | | *
|
||||
// * v Refers 80 v v 20 | *
|
||||
// * /----------------\ /----------------\ | *
|
||||
// * | scud (basic) |<------------------------| stud (basic) | | *
|
||||
// * \----------------/ 20 Registers | (Upgrades to | | 5 *
|
||||
// * | Lifetime) | v *
|
||||
// * \----------------/ /--------------\ *
|
||||
// * L------->| pleb (Basic) | *
|
||||
// * 95 Refers \--------------/ *
|
||||
// * *
|
||||
// * Fee distribution chains (80-20 referral/net split, 50-30 referrer/LTM split) *
|
||||
// * life : 80% -> life, 20% -> net *
|
||||
// * rog: 80% -> rog, 20% -> net *
|
||||
// * ann (before upg): 80% -> life, 20% -> net *
|
||||
// * ann (after upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% -> net *
|
||||
// * stud (before upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> rog, *
|
||||
// * 20% -> net *
|
||||
// * stud (after upg): 80% -> stud, 20% -> net *
|
||||
// * dumy : 75% * 80% -> life, 25% * 80% -> rog, 20% -> net *
|
||||
// * scud : 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> stud, 20% -> net *
|
||||
// * pleb : 95% * 80% -> stud, 5% * 80% -> rog, 20% -> net *
|
||||
// */
|
||||
BOOST_AUTO_TEST_CASE( cashback_test )
|
||||
{ try {
|
||||
/* Account Structure used in this test *
|
||||
* *
|
||||
* /-----------------\ /-------------------\ *
|
||||
* | life (Lifetime) | | rog (Lifetime) | *
|
||||
* \-----------------/ \-------------------/ *
|
||||
* | Ref&Reg | Refers | Registers | Registers *
|
||||
* | | 75 | 25 | *
|
||||
* v v v | *
|
||||
* /----------------\ /----------------\ | *
|
||||
* | ann (Annual) | | dumy (basic) | | *
|
||||
* \----------------/ \----------------/ |-------------. *
|
||||
* 80 | Refers L--------------------------------. | | *
|
||||
* v Refers 80 v v 20 | *
|
||||
* /----------------\ /----------------\ | *
|
||||
* | scud (basic) |<------------------------| stud (basic) | | *
|
||||
* \----------------/ 20 Registers | (Upgrades to | | 5 *
|
||||
* | Lifetime) | v *
|
||||
* \----------------/ /--------------\ *
|
||||
* L------->| pleb (Basic) | *
|
||||
* 95 Refers \--------------/ *
|
||||
* *
|
||||
* Fee distribution chains (80-20 referral/net split, 50-30 referrer/LTM split) *
|
||||
* life : 80% -> life, 20% -> net *
|
||||
* rog: 80% -> rog, 20% -> net *
|
||||
* ann (before upg): 80% -> life, 20% -> net *
|
||||
* ann (after upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% -> net *
|
||||
* stud (before upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> rog, *
|
||||
* 20% -> net *
|
||||
* stud (after upg): 80% -> stud, 20% -> net *
|
||||
* dumy : 75% * 80% -> life, 25% * 80% -> rog, 20% -> net *
|
||||
* scud : 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> stud, 20% -> net *
|
||||
* pleb : 95% * 80% -> stud, 5% * 80% -> rog, 20% -> net *
|
||||
*/
|
||||
|
||||
// BOOST_TEST_MESSAGE("Creating actors");
|
||||
BOOST_TEST_MESSAGE("Creating actors");
|
||||
|
||||
// ACTOR(life);
|
||||
// ACTOR(rog);
|
||||
// PREP_ACTOR(ann);
|
||||
// PREP_ACTOR(scud);
|
||||
// PREP_ACTOR(dumy);
|
||||
// PREP_ACTOR(stud);
|
||||
// PREP_ACTOR(pleb);
|
||||
ACTOR(life);
|
||||
ACTOR(rog);
|
||||
PREP_ACTOR(ann);
|
||||
PREP_ACTOR(scud);
|
||||
PREP_ACTOR(dumy);
|
||||
PREP_ACTOR(stud);
|
||||
PREP_ACTOR(pleb);
|
||||
|
||||
// account_id_type ann_id, scud_id, dumy_id, stud_id, pleb_id;
|
||||
// actor_audit alife, arog, aann, ascud, adumy, astud, apleb;
|
||||
account_id_type ann_id, scud_id, dumy_id, stud_id, pleb_id;
|
||||
actor_audit alife, arog, aann, ascud, adumy, astud, apleb;
|
||||
|
||||
// alife.b0 = 100000000;
|
||||
// arog.b0 = 100000000;
|
||||
// aann.b0 = 1000000;
|
||||
// astud.b0 = 1000000;
|
||||
// astud.ref_pct = 80 * GRAPHENE_1_PERCENT;
|
||||
// ascud.ref_pct = 80 * GRAPHENE_1_PERCENT;
|
||||
// adumy.ref_pct = 75 * GRAPHENE_1_PERCENT;
|
||||
// apleb.ref_pct = 95 * GRAPHENE_1_PERCENT;
|
||||
alife.b0 = 100000000;
|
||||
arog.b0 = 100000000;
|
||||
aann.b0 = 1000000;
|
||||
astud.b0 = 1000000;
|
||||
astud.ref_pct = 80 * GRAPHENE_1_PERCENT;
|
||||
ascud.ref_pct = 80 * GRAPHENE_1_PERCENT;
|
||||
adumy.ref_pct = 75 * GRAPHENE_1_PERCENT;
|
||||
apleb.ref_pct = 95 * GRAPHENE_1_PERCENT;
|
||||
|
||||
// transfer(account_id_type(), life_id, asset(alife.b0));
|
||||
// alife.bal += alife.b0;
|
||||
// transfer(account_id_type(), rog_id, asset(arog.b0));
|
||||
// arog.bal += arog.b0;
|
||||
// upgrade_to_lifetime_member(life_id);
|
||||
// upgrade_to_lifetime_member(rog_id);
|
||||
transfer(account_id_type(), life_id, asset(alife.b0));
|
||||
alife.bal += alife.b0;
|
||||
transfer(account_id_type(), rog_id, asset(arog.b0));
|
||||
arog.bal += arog.b0;
|
||||
upgrade_to_lifetime_member(life_id);
|
||||
upgrade_to_lifetime_member(rog_id);
|
||||
|
||||
// BOOST_TEST_MESSAGE("Enable fees");
|
||||
// const auto& fees = db.get_global_properties().parameters.current_fees;
|
||||
BOOST_TEST_MESSAGE("Enable fees");
|
||||
const auto& fees = db.get_global_properties().parameters.current_fees;
|
||||
|
||||
// #define CustomRegisterActor(actor_name, registrar_name, referrer_name, referrer_rate) \
|
||||
// { \
|
||||
// account_create_operation op; \
|
||||
// op.registrar = registrar_name ## _id; \
|
||||
// op.referrer = referrer_name ## _id; \
|
||||
// op.referrer_percent = referrer_rate*GRAPHENE_1_PERCENT; \
|
||||
// op.name = BOOST_PP_STRINGIZE(actor_name); \
|
||||
// op.options.memo_key = actor_name ## _private_key.get_public_key(); \
|
||||
// op.active = authority(1, public_key_type(actor_name ## _private_key.get_public_key()), 1); \
|
||||
// op.owner = op.active; \
|
||||
// op.fee = fees->calculate_fee(op); \
|
||||
// trx.operations = {op}; \
|
||||
// sign( trx, registrar_name ## _private_key ); \
|
||||
// actor_name ## _id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>(); \
|
||||
// trx.clear(); \
|
||||
// }
|
||||
// #define CustomAuditActor(actor_name) \
|
||||
// if( actor_name ## _id != account_id_type() ) \
|
||||
// { \
|
||||
// CHECK_BALANCE( actor_name, a ## actor_name.bal ); \
|
||||
// CHECK_VESTED_CASHBACK( actor_name, a ## actor_name.vcb ); \
|
||||
// CHECK_UNVESTED_CASHBACK( actor_name, a ## actor_name.ucb ); \
|
||||
// CHECK_CASHBACK_VBO( actor_name, a ## actor_name.ubal ); \
|
||||
// }
|
||||
#define CustomRegisterActor(actor_name, registrar_name, referrer_name, referrer_rate) \
|
||||
{ \
|
||||
account_create_operation op; \
|
||||
op.registrar = registrar_name ## _id; \
|
||||
op.referrer = referrer_name ## _id; \
|
||||
op.referrer_percent = referrer_rate*GRAPHENE_1_PERCENT; \
|
||||
op.name = BOOST_PP_STRINGIZE(actor_name); \
|
||||
op.options.memo_key = actor_name ## _private_key.get_public_key(); \
|
||||
op.active = authority(1, public_key_type(actor_name ## _private_key.get_public_key()), 1); \
|
||||
op.owner = op.active; \
|
||||
op.fee = fees->calculate_fee(op); \
|
||||
trx.operations = {op}; \
|
||||
sign( trx, registrar_name ## _private_key ); \
|
||||
actor_name ## _id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>(); \
|
||||
trx.clear(); \
|
||||
}
|
||||
#define CustomAuditActor(actor_name) \
|
||||
if( actor_name ## _id != account_id_type() ) \
|
||||
{ \
|
||||
CHECK_BALANCE( actor_name, a ## actor_name.bal ); \
|
||||
CHECK_VESTED_CASHBACK( actor_name, a ## actor_name.vcb ); \
|
||||
CHECK_UNVESTED_CASHBACK( actor_name, a ## actor_name.ucb ); \
|
||||
CHECK_CASHBACK_VBO( actor_name, a ## actor_name.ubal ); \
|
||||
}
|
||||
|
||||
// #define CustomAudit() \
|
||||
// { \
|
||||
// CustomAuditActor( life ); \
|
||||
// CustomAuditActor( rog ); \
|
||||
// CustomAuditActor( ann ); \
|
||||
// CustomAuditActor( stud ); \
|
||||
// CustomAuditActor( dumy ); \
|
||||
// CustomAuditActor( scud ); \
|
||||
// CustomAuditActor( pleb ); \
|
||||
// }
|
||||
#define CustomAudit() \
|
||||
{ \
|
||||
CustomAuditActor( life ); \
|
||||
CustomAuditActor( rog ); \
|
||||
CustomAuditActor( ann ); \
|
||||
CustomAuditActor( stud ); \
|
||||
CustomAuditActor( dumy ); \
|
||||
CustomAuditActor( scud ); \
|
||||
CustomAuditActor( pleb ); \
|
||||
}
|
||||
|
||||
// int64_t reg_fee = fees->get< account_create_operation >().premium_fee;
|
||||
// int64_t xfer_fee = fees->get< transfer_operation >().fee;
|
||||
// int64_t upg_an_fee = fees->get< account_upgrade_operation >().membership_annual_fee;
|
||||
// int64_t upg_lt_fee = fees->get< account_upgrade_operation >().membership_lifetime_fee;
|
||||
// // all percentages here are cut from whole pie!
|
||||
// uint64_t network_pct = 20 * P1;
|
||||
// uint64_t lt_pct = 375 * P100 / 1000;
|
||||
int64_t reg_fee = fees->get< account_create_operation >().premium_fee;
|
||||
int64_t xfer_fee = fees->get< transfer_operation >().fee;
|
||||
int64_t upg_an_fee = fees->get< account_upgrade_operation >().membership_annual_fee;
|
||||
int64_t upg_lt_fee = fees->get< account_upgrade_operation >().membership_lifetime_fee;
|
||||
// all percentages here are cut from whole pie!
|
||||
uint64_t network_pct = 20 * P1;
|
||||
uint64_t lt_pct = 375 * P100 / 1000;
|
||||
|
||||
// BOOST_TEST_MESSAGE("Register and upgrade Ann");
|
||||
// {
|
||||
// CustomRegisterActor(ann, life, life, 75);
|
||||
// alife.vcb += reg_fee; alife.bal += -reg_fee;
|
||||
// CustomAudit();
|
||||
BOOST_TEST_MESSAGE("Register and upgrade Ann");
|
||||
{
|
||||
CustomRegisterActor(ann, life, life, 75);
|
||||
alife.vcb += reg_fee; alife.bal += -reg_fee;
|
||||
CustomAudit();
|
||||
|
||||
// transfer(life_id, ann_id, asset(aann.b0));
|
||||
// alife.vcb += xfer_fee; alife.bal += -xfer_fee -aann.b0; aann.bal += aann.b0;
|
||||
// CustomAudit();
|
||||
transfer(life_id, ann_id, asset(aann.b0));
|
||||
alife.vcb += xfer_fee; alife.bal += -xfer_fee -aann.b0; aann.bal += aann.b0;
|
||||
CustomAudit();
|
||||
|
||||
// upgrade_to_annual_member(ann_id);
|
||||
// aann.ucb += upg_an_fee; aann.bal += -upg_an_fee;
|
||||
upgrade_to_annual_member(ann_id);
|
||||
aann.ucb += upg_an_fee; aann.bal += -upg_an_fee;
|
||||
|
||||
// // audit distribution of fees from Ann
|
||||
// alife.ubal += pct( P100-network_pct, aann.ucb );
|
||||
// alife.bal += pct( P100-network_pct, aann.vcb );
|
||||
// aann.ucb = 0; aann.vcb = 0;
|
||||
// CustomAudit();
|
||||
// }
|
||||
// audit distribution of fees from Ann
|
||||
alife.ubal += pct( P100-network_pct, aann.ucb );
|
||||
alife.bal += pct( P100-network_pct, aann.vcb );
|
||||
aann.ucb = 0; aann.vcb = 0;
|
||||
CustomAudit();
|
||||
}
|
||||
|
||||
// BOOST_TEST_MESSAGE("Register dumy and stud");
|
||||
// CustomRegisterActor(dumy, rog, life, 75);
|
||||
// arog.vcb += reg_fee; arog.bal += -reg_fee;
|
||||
// CustomAudit();
|
||||
BOOST_TEST_MESSAGE("Register dumy and stud");
|
||||
CustomRegisterActor(dumy, rog, life, 75);
|
||||
arog.vcb += reg_fee; arog.bal += -reg_fee;
|
||||
CustomAudit();
|
||||
|
||||
// CustomRegisterActor(stud, rog, ann, 80);
|
||||
// arog.vcb += reg_fee; arog.bal += -reg_fee;
|
||||
// CustomAudit();
|
||||
CustomRegisterActor(stud, rog, ann, 80);
|
||||
arog.vcb += reg_fee; arog.bal += -reg_fee;
|
||||
CustomAudit();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Upgrade stud to lifetime member");
|
||||
BOOST_TEST_MESSAGE("Upgrade stud to lifetime member");
|
||||
|
||||
// transfer(life_id, stud_id, asset(astud.b0));
|
||||
// alife.vcb += xfer_fee; alife.bal += -astud.b0 -xfer_fee; astud.bal += astud.b0;
|
||||
// CustomAudit();
|
||||
transfer(life_id, stud_id, asset(astud.b0));
|
||||
alife.vcb += xfer_fee; alife.bal += -astud.b0 -xfer_fee; astud.bal += astud.b0;
|
||||
CustomAudit();
|
||||
|
||||
// upgrade_to_lifetime_member(stud_id);
|
||||
// astud.ucb += upg_lt_fee; astud.bal -= upg_lt_fee;
|
||||
upgrade_to_lifetime_member(stud_id);
|
||||
astud.ucb += upg_lt_fee; astud.bal -= upg_lt_fee;
|
||||
|
||||
// /*
|
||||
// network_cut: 20000
|
||||
// referrer_cut: 40000 -> ann
|
||||
// registrar_cut: 10000 -> rog
|
||||
// lifetime_cut: 30000 -> life
|
||||
/*
|
||||
network_cut: 20000
|
||||
referrer_cut: 40000 -> ann
|
||||
registrar_cut: 10000 -> rog
|
||||
lifetime_cut: 30000 -> life
|
||||
|
||||
// NET : net
|
||||
// LTM : net' ltm
|
||||
// REF : net' ltm' ref
|
||||
// REG : net' ltm' ref'
|
||||
// */
|
||||
NET : net
|
||||
LTM : net' ltm
|
||||
REF : net' ltm' ref
|
||||
REG : net' ltm' ref'
|
||||
*/
|
||||
|
||||
// // audit distribution of fees from stud
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, astud.ucb );
|
||||
// aann.ubal += pct( P100-network_pct, P100-lt_pct, astud.ref_pct, astud.ucb );
|
||||
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-astud.ref_pct, astud.ucb );
|
||||
// astud.ucb = 0;
|
||||
// CustomAudit();
|
||||
// audit distribution of fees from stud
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, astud.ucb );
|
||||
aann.ubal += pct( P100-network_pct, P100-lt_pct, astud.ref_pct, astud.ucb );
|
||||
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-astud.ref_pct, astud.ucb );
|
||||
astud.ucb = 0;
|
||||
CustomAudit();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Register pleb and scud");
|
||||
BOOST_TEST_MESSAGE("Register pleb and scud");
|
||||
|
||||
// CustomRegisterActor(pleb, rog, stud, 95);
|
||||
// arog.vcb += reg_fee; arog.bal += -reg_fee;
|
||||
// CustomAudit();
|
||||
CustomRegisterActor(pleb, rog, stud, 95);
|
||||
arog.vcb += reg_fee; arog.bal += -reg_fee;
|
||||
CustomAudit();
|
||||
|
||||
// CustomRegisterActor(scud, stud, ann, 80);
|
||||
// astud.vcb += reg_fee; astud.bal += -reg_fee;
|
||||
// CustomAudit();
|
||||
CustomRegisterActor(scud, stud, ann, 80);
|
||||
astud.vcb += reg_fee; astud.bal += -reg_fee;
|
||||
CustomAudit();
|
||||
|
||||
// generate_block();
|
||||
generate_block();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Wait for maintenance interval");
|
||||
BOOST_TEST_MESSAGE("Wait for maintenance interval");
|
||||
|
||||
// generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
// // audit distribution of fees from life
|
||||
// alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
|
||||
// alife.ucb = 0; alife.vcb = 0;
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
// audit distribution of fees from life
|
||||
alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
|
||||
alife.ucb = 0; alife.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from rog
|
||||
// arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
|
||||
// arog.ucb = 0; arog.vcb = 0;
|
||||
// audit distribution of fees from rog
|
||||
arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
|
||||
arog.ucb = 0; arog.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from ann
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
|
||||
// aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
|
||||
// alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
|
||||
// aann.ucb = 0; aann.vcb = 0;
|
||||
// audit distribution of fees from ann
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
|
||||
aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
|
||||
alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
|
||||
aann.ucb = 0; aann.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from stud
|
||||
// astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
|
||||
// astud.ucb = 0; astud.vcb = 0;
|
||||
// audit distribution of fees from stud
|
||||
astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
|
||||
astud.ucb = 0; astud.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from dumy
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
|
||||
// alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
// adumy.ucb = 0; adumy.vcb = 0;
|
||||
// audit distribution of fees from dumy
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
|
||||
alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
adumy.ucb = 0; adumy.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from scud
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
|
||||
// aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
// astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
// ascud.ucb = 0; ascud.vcb = 0;
|
||||
// audit distribution of fees from scud
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
|
||||
aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
ascud.ucb = 0; ascud.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from pleb
|
||||
// astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
|
||||
// astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
// apleb.ucb = 0; apleb.vcb = 0;
|
||||
// audit distribution of fees from pleb
|
||||
astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
|
||||
astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
apleb.ucb = 0; apleb.vcb = 0;
|
||||
|
||||
// CustomAudit();
|
||||
CustomAudit();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Doing some transfers");
|
||||
BOOST_TEST_MESSAGE("Doing some transfers");
|
||||
|
||||
// transfer(stud_id, scud_id, asset(500000));
|
||||
// astud.bal += -500000-xfer_fee; astud.vcb += xfer_fee; ascud.bal += 500000;
|
||||
// CustomAudit();
|
||||
transfer(stud_id, scud_id, asset(500000));
|
||||
astud.bal += -500000-xfer_fee; astud.vcb += xfer_fee; ascud.bal += 500000;
|
||||
CustomAudit();
|
||||
|
||||
// transfer(scud_id, pleb_id, asset(400000));
|
||||
// ascud.bal += -400000-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 400000;
|
||||
// CustomAudit();
|
||||
transfer(scud_id, pleb_id, asset(400000));
|
||||
ascud.bal += -400000-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 400000;
|
||||
CustomAudit();
|
||||
|
||||
// transfer(pleb_id, dumy_id, asset(300000));
|
||||
// apleb.bal += -300000-xfer_fee; apleb.vcb += xfer_fee; adumy.bal += 300000;
|
||||
// CustomAudit();
|
||||
transfer(pleb_id, dumy_id, asset(300000));
|
||||
apleb.bal += -300000-xfer_fee; apleb.vcb += xfer_fee; adumy.bal += 300000;
|
||||
CustomAudit();
|
||||
|
||||
// transfer(dumy_id, rog_id, asset(200000));
|
||||
// adumy.bal += -200000-xfer_fee; adumy.vcb += xfer_fee; arog.bal += 200000;
|
||||
// CustomAudit();
|
||||
transfer(dumy_id, rog_id, asset(200000));
|
||||
adumy.bal += -200000-xfer_fee; adumy.vcb += xfer_fee; arog.bal += 200000;
|
||||
CustomAudit();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Waiting for maintenance time");
|
||||
BOOST_TEST_MESSAGE("Waiting for maintenance time");
|
||||
|
||||
// generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
|
||||
// // audit distribution of fees from life
|
||||
// alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
|
||||
// alife.ucb = 0; alife.vcb = 0;
|
||||
// audit distribution of fees from life
|
||||
alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
|
||||
alife.ucb = 0; alife.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from rog
|
||||
// arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
|
||||
// arog.ucb = 0; arog.vcb = 0;
|
||||
// audit distribution of fees from rog
|
||||
arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
|
||||
arog.ucb = 0; arog.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from ann
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
|
||||
// aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
|
||||
// alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
|
||||
// aann.ucb = 0; aann.vcb = 0;
|
||||
// audit distribution of fees from ann
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
|
||||
aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
|
||||
alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
|
||||
aann.ucb = 0; aann.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from stud
|
||||
// astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
|
||||
// astud.ucb = 0; astud.vcb = 0;
|
||||
// audit distribution of fees from stud
|
||||
astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
|
||||
astud.ucb = 0; astud.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from dumy
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
|
||||
// alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
// adumy.ucb = 0; adumy.vcb = 0;
|
||||
// audit distribution of fees from dumy
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
|
||||
alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
|
||||
adumy.ucb = 0; adumy.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from scud
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
|
||||
// aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
// astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
// ascud.ucb = 0; ascud.vcb = 0;
|
||||
// audit distribution of fees from scud
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
|
||||
aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
ascud.ucb = 0; ascud.vcb = 0;
|
||||
|
||||
// // audit distribution of fees from pleb
|
||||
// astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
|
||||
// astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
// apleb.ucb = 0; apleb.vcb = 0;
|
||||
// audit distribution of fees from pleb
|
||||
astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
|
||||
astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
|
||||
apleb.ucb = 0; apleb.vcb = 0;
|
||||
|
||||
// CustomAudit();
|
||||
CustomAudit();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Waiting for annual membership to expire");
|
||||
BOOST_TEST_MESSAGE("Waiting for annual membership to expire");
|
||||
BOOST_TEST_MESSAGE("Count of block to generate " + std::to_string(ann_id(db).membership_expiration_date.sec_since_epoch()));
|
||||
|
||||
// generate_blocks(ann_id(db).membership_expiration_date);
|
||||
// generate_block();
|
||||
generate_blocks(ann_id(db).membership_expiration_date);
|
||||
generate_block();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Transferring from scud to pleb");
|
||||
BOOST_TEST_MESSAGE("Transferring from scud to pleb");
|
||||
|
||||
// //ann's membership has expired, so scud's fee should go up to life instead.
|
||||
// transfer(scud_id, pleb_id, asset(10));
|
||||
// ascud.bal += -10-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 10;
|
||||
// CustomAudit();
|
||||
//ann's membership has expired, so scud's fee should go up to life instead.
|
||||
transfer(scud_id, pleb_id, asset(10));
|
||||
ascud.bal += -10-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 10;
|
||||
CustomAudit();
|
||||
|
||||
// BOOST_TEST_MESSAGE("Waiting for maint interval");
|
||||
BOOST_TEST_MESSAGE("Waiting for maint interval");
|
||||
|
||||
// generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
|
||||
// // audit distribution of fees from scud
|
||||
// alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
|
||||
// alife.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
// astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
// ascud.ucb = 0; ascud.vcb = 0;
|
||||
// audit distribution of fees from scud
|
||||
alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
|
||||
alife.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
|
||||
ascud.ucb = 0; ascud.vcb = 0;
|
||||
|
||||
// CustomAudit();
|
||||
CustomAudit();
|
||||
|
||||
// } FC_LOG_AND_RETHROW() }
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_AUTO_TEST_CASE( account_create_fee_scaling )
|
||||
{ try {
|
||||
|
|
@ -1033,7 +1036,6 @@ BOOST_AUTO_TEST_CASE( issue_429_test )
|
|||
|
||||
verify_asset_supplies( db );
|
||||
|
||||
generate_blocks( HARDFORK_CORE_429_TIME + 10 );
|
||||
{
|
||||
signed_transaction tx;
|
||||
asset_create_operation op;
|
||||
|
|
@ -1046,7 +1048,7 @@ BOOST_AUTO_TEST_CASE( issue_429_test )
|
|||
sign( tx, alice_private_key );
|
||||
PUSH_TX( db, tx );
|
||||
}
|
||||
|
||||
|
||||
verify_asset_supplies( db );
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
|
|
|
|||
|
|
@ -99,8 +99,7 @@ BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_tw
|
|||
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -153,8 +152,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplication_in_transaction_with_several_op
|
|||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
|
||||
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -174,8 +172,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_w
|
|||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
|
||||
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -194,8 +191,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_w
|
|||
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -229,8 +225,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_same_member_create_operations )
|
|||
create_proposal(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -269,9 +264,7 @@ BOOST_AUTO_TEST_CASE( check_failes_for_several_operations_of_mixed_type )
|
|||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)), //duplicate
|
||||
make_committee_member_create_operation(asset(1002), account_id_type(), "test url")});
|
||||
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1112,6 +1112,633 @@ BOOST_AUTO_TEST_CASE( uia_fees )
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE( dividend_tests, database_fixture )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( create_dividend_uia )
|
||||
{
|
||||
using namespace graphene;
|
||||
try {
|
||||
BOOST_TEST_MESSAGE("Creating dividend holder asset");
|
||||
{
|
||||
asset_create_operation creator;
|
||||
creator.issuer = account_id_type();
|
||||
creator.fee = asset();
|
||||
creator.symbol = "DIVIDEND";
|
||||
creator.common_options.max_supply = 100000000;
|
||||
creator.precision = 2;
|
||||
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
|
||||
creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
|
||||
creator.common_options.flags = charge_market_fee;
|
||||
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
|
||||
trx.operations.push_back(std::move(creator));
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE("Creating test accounts");
|
||||
create_account("alice");
|
||||
create_account("bob");
|
||||
create_account("carol");
|
||||
create_account("dave");
|
||||
create_account("frank");
|
||||
|
||||
BOOST_TEST_MESSAGE("Creating test asset");
|
||||
{
|
||||
asset_create_operation creator;
|
||||
creator.issuer = account_id_type();
|
||||
creator.fee = asset();
|
||||
creator.symbol = "TEST";
|
||||
creator.common_options.max_supply = 100000000;
|
||||
creator.precision = 2;
|
||||
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
|
||||
creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
|
||||
creator.common_options.flags = charge_market_fee;
|
||||
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
|
||||
trx.operations.push_back(std::move(creator));
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE("Funding asset fee pool");
|
||||
{
|
||||
asset_fund_fee_pool_operation fund_op;
|
||||
fund_op.from_account = account_id_type();
|
||||
fund_op.asset_id = get_asset("TEST").id;
|
||||
fund_op.amount = 500000000;
|
||||
trx.operations.push_back(std::move(fund_op));
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
|
||||
// our DIVIDEND asset should not yet be a divdend asset
|
||||
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
|
||||
BOOST_CHECK(!dividend_holder_asset_object.dividend_data_id);
|
||||
|
||||
BOOST_TEST_MESSAGE("Converting the new asset to a dividend holder asset");
|
||||
{
|
||||
asset_update_dividend_operation op;
|
||||
op.issuer = dividend_holder_asset_object.issuer;
|
||||
op.asset_to_update = dividend_holder_asset_object.id;
|
||||
op.new_options.next_payout_time = db.head_block_time() + fc::minutes(1);
|
||||
op.new_options.payout_interval = 60 * 60 * 24 * 3;
|
||||
|
||||
trx.operations.push_back(op);
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE("Verifying the dividend holder asset options");
|
||||
BOOST_REQUIRE(dividend_holder_asset_object.dividend_data_id);
|
||||
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
|
||||
{
|
||||
BOOST_REQUIRE(dividend_data.options.payout_interval);
|
||||
BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 60 * 60 * 24 * 3);
|
||||
}
|
||||
|
||||
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
|
||||
BOOST_CHECK_EQUAL(dividend_distribution_account.name, "dividend-dividend-distribution");
|
||||
|
||||
// db.modify( db.get_global_properties(), [&]( global_property_object& _gpo )
|
||||
// {
|
||||
// _gpo.parameters.current_fees->get<asset_dividend_distribution_operation>().distribution_base_fee = 100;
|
||||
// _gpo.parameters.current_fees->get<asset_dividend_distribution_operation>().distribution_fee_per_holder = 100;
|
||||
// } );
|
||||
|
||||
|
||||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_update_dividend_interval )
|
||||
{
|
||||
using namespace graphene;
|
||||
try {
|
||||
INVOKE( create_dividend_uia );
|
||||
|
||||
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
|
||||
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
|
||||
|
||||
auto advance_to_next_payout_time = [&]() {
|
||||
// Advance to the next upcoming payout time
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
||||
// generate blocks up to the next scheduled time
|
||||
generate_blocks(next_payout_scheduled_time);
|
||||
// if the scheduled time fell on a maintenance interval, then we should have paid out.
|
||||
// if not, we need to advance to the next maintenance interval to trigger the payout
|
||||
if (dividend_data.options.next_payout_time)
|
||||
{
|
||||
// we know there was a next_payout_time set when we entered this, so if
|
||||
// it has been cleared, we must have already processed payouts, no need to
|
||||
// further advance time.
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_TEST_MESSAGE("Updating the payout interval");
|
||||
{
|
||||
asset_update_dividend_operation op;
|
||||
op.issuer = dividend_holder_asset_object.issuer;
|
||||
op.asset_to_update = dividend_holder_asset_object.id;
|
||||
op.new_options.next_payout_time = fc::time_point::now() + fc::minutes(1);
|
||||
op.new_options.payout_interval = 60 * 60 * 24; // 1 days
|
||||
trx.operations.push_back(op);
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE("Verifying the updated dividend holder asset options");
|
||||
{
|
||||
BOOST_REQUIRE(dividend_data.options.payout_interval);
|
||||
BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 60 * 60 * 24);
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE("Removing the payout interval");
|
||||
{
|
||||
asset_update_dividend_operation op;
|
||||
op.issuer = dividend_holder_asset_object.issuer;
|
||||
op.asset_to_update = dividend_holder_asset_object.id;
|
||||
op.new_options.next_payout_time = dividend_data.options.next_payout_time;
|
||||
op.new_options.payout_interval = fc::optional<uint32_t>();
|
||||
trx.operations.push_back(op);
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
generate_block();
|
||||
BOOST_CHECK(!dividend_data.options.payout_interval);
|
||||
advance_to_next_payout_time();
|
||||
BOOST_REQUIRE_MESSAGE(!dividend_data.options.next_payout_time, "A new payout was scheduled, but none should have been");
|
||||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_basic_dividend_distribution )
|
||||
{
|
||||
using namespace graphene;
|
||||
try {
|
||||
INVOKE( create_dividend_uia );
|
||||
|
||||
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
|
||||
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
|
||||
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
|
||||
const account_object& alice = get_account("alice");
|
||||
const account_object& bob = get_account("bob");
|
||||
const account_object& carol = get_account("carol");
|
||||
const account_object& dave = get_account("dave");
|
||||
const account_object& frank = get_account("frank");
|
||||
const auto& test_asset_object = get_asset("TEST");
|
||||
|
||||
auto issue_asset_to_account = [&](const asset_object& asset_to_issue, const account_object& destination_account, int64_t amount_to_issue)
|
||||
{
|
||||
asset_issue_operation op;
|
||||
op.issuer = asset_to_issue.issuer;
|
||||
op.asset_to_issue = asset(amount_to_issue, asset_to_issue.id);
|
||||
op.issue_to_account = destination_account.id;
|
||||
trx.operations.push_back( op );
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
};
|
||||
|
||||
auto verify_pending_balance = [&](const account_object& holder_account_obj, const asset_object& payout_asset_obj, int64_t expected_balance) {
|
||||
int64_t pending_balance = get_dividend_pending_payout_balance(dividend_holder_asset_object.id,
|
||||
holder_account_obj.id,
|
||||
payout_asset_obj.id);
|
||||
BOOST_CHECK_EQUAL(pending_balance, expected_balance);
|
||||
};
|
||||
|
||||
auto advance_to_next_payout_time = [&]() {
|
||||
// Advance to the next upcoming payout time
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
||||
// generate blocks up to the next scheduled time
|
||||
generate_blocks(next_payout_scheduled_time);
|
||||
// if the scheduled time fell on a maintenance interval, then we should have paid out.
|
||||
// if not, we need to advance to the next maintenance interval to trigger the payout
|
||||
if (dividend_data.options.next_payout_time)
|
||||
{
|
||||
// we know there was a next_payout_time set when we entered this, so if
|
||||
// it has been cleared, we must have already processed payouts, no need to
|
||||
// further advance time.
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
}
|
||||
};
|
||||
|
||||
// the first test will be testing pending balances, so we need to hit a
|
||||
// maintenance interval that isn't the payout interval. Payout is
|
||||
// every 3 days, maintenance interval is every 1 day.
|
||||
advance_to_next_payout_time();
|
||||
|
||||
// Set up the first test, issue alice, bob, and carol each 100 DIVIDEND.
|
||||
// Then deposit 300 TEST in the distribution account, and see that they
|
||||
// each are credited 100 TEST.
|
||||
issue_asset_to_account(dividend_holder_asset_object, alice, 100000);
|
||||
issue_asset_to_account(dividend_holder_asset_object, bob, 100000);
|
||||
issue_asset_to_account(dividend_holder_asset_object, carol, 100000);
|
||||
|
||||
BOOST_TEST_MESSAGE("Issuing 300 TEST to the dividend account");
|
||||
issue_asset_to_account(test_asset_object, dividend_distribution_account, 30000);
|
||||
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
|
||||
verify_pending_balance(alice, test_asset_object, 10000);
|
||||
verify_pending_balance(bob, test_asset_object, 10000);
|
||||
verify_pending_balance(carol, test_asset_object, 10000);
|
||||
|
||||
// For the second test, issue carol more than the other two, so it's
|
||||
// alice: 100 DIVIDND, bob: 100 DIVIDEND, carol: 200 DIVIDEND
|
||||
// Then deposit 400 TEST in the distribution account, and see that alice
|
||||
// and bob are credited with 100 TEST, and carol gets 200 TEST
|
||||
BOOST_TEST_MESSAGE("Issuing carol twice as much of the holder asset");
|
||||
issue_asset_to_account(dividend_holder_asset_object, carol, 100000); // one thousand at two digits of precision
|
||||
issue_asset_to_account(test_asset_object, dividend_distribution_account, 40000); // one thousand at two digits of precision
|
||||
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
verify_pending_balance(alice, test_asset_object, 20000);
|
||||
verify_pending_balance(bob, test_asset_object, 20000);
|
||||
verify_pending_balance(carol, test_asset_object, 30000);
|
||||
|
||||
fc::time_point_sec old_next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
||||
advance_to_next_payout_time();
|
||||
|
||||
|
||||
BOOST_REQUIRE_MESSAGE(dividend_data.options.next_payout_time, "No new payout was scheduled");
|
||||
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time != *dividend_data.options.next_payout_time,
|
||||
"New payout was scheduled for the same time as the last payout");
|
||||
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time + *dividend_data.options.payout_interval == *dividend_data.options.next_payout_time,
|
||||
"New payout was not scheduled for the expected time");
|
||||
|
||||
auto verify_dividend_payout_operations = [&](const account_object& destination_account, const asset& expected_payout)
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Verifying the virtual op was created");
|
||||
const account_transaction_history_index& hist_idx = db.get_index_type<account_transaction_history_index>();
|
||||
auto account_history_range = hist_idx.indices().get<by_seq>().equal_range(boost::make_tuple(destination_account.id));
|
||||
BOOST_REQUIRE(account_history_range.first != account_history_range.second);
|
||||
const operation_history_object& history_object = std::prev(account_history_range.second)->operation_id(db);
|
||||
const asset_dividend_distribution_operation& distribution_operation = history_object.op.get<asset_dividend_distribution_operation>();
|
||||
BOOST_CHECK(distribution_operation.account_id == destination_account.id);
|
||||
BOOST_CHECK(std::find(distribution_operation.amounts.begin(), distribution_operation.amounts.end(), expected_payout)
|
||||
!= distribution_operation.amounts.end());
|
||||
};
|
||||
|
||||
BOOST_TEST_MESSAGE("Verifying the payouts");
|
||||
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 20000);
|
||||
verify_dividend_payout_operations(alice, asset(20000, test_asset_object.id));
|
||||
verify_pending_balance(alice, test_asset_object, 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 20000);
|
||||
verify_dividend_payout_operations(bob, asset(20000, test_asset_object.id));
|
||||
verify_pending_balance(bob, test_asset_object, 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 30000);
|
||||
verify_dividend_payout_operations(carol, asset(30000, test_asset_object.id));
|
||||
verify_pending_balance(carol, test_asset_object, 0);
|
||||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_basic_dividend_distribution_to_core_asset )
|
||||
{
|
||||
using namespace graphene;
|
||||
try {
|
||||
BOOST_TEST_MESSAGE("Creating test accounts");
|
||||
create_account("alice");
|
||||
create_account("bob");
|
||||
create_account("carol");
|
||||
create_account("dave");
|
||||
create_account("frank");
|
||||
|
||||
BOOST_TEST_MESSAGE("Creating test asset");
|
||||
{
|
||||
asset_create_operation creator;
|
||||
creator.issuer = account_id_type();
|
||||
creator.fee = asset();
|
||||
creator.symbol = "TEST";
|
||||
creator.common_options.max_supply = 100000000;
|
||||
creator.precision = 2;
|
||||
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
|
||||
creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
|
||||
creator.common_options.flags = charge_market_fee;
|
||||
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
|
||||
trx.operations.push_back(std::move(creator));
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
generate_block();
|
||||
|
||||
const auto& dividend_holder_asset_object = asset_id_type(0)(db);
|
||||
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
|
||||
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
|
||||
const account_object& alice = get_account("alice");
|
||||
const account_object& bob = get_account("bob");
|
||||
const account_object& carol = get_account("carol");
|
||||
const account_object& dave = get_account("dave");
|
||||
const account_object& frank = get_account("frank");
|
||||
const auto& test_asset_object = get_asset("TEST");
|
||||
|
||||
auto issue_asset_to_account = [&](const asset_object& asset_to_issue, const account_object& destination_account, int64_t amount_to_issue)
|
||||
{
|
||||
asset_issue_operation op;
|
||||
op.issuer = asset_to_issue.issuer;
|
||||
op.asset_to_issue = asset(amount_to_issue, asset_to_issue.id);
|
||||
op.issue_to_account = destination_account.id;
|
||||
trx.operations.push_back( op );
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
};
|
||||
|
||||
auto verify_pending_balance = [&](const account_object& holder_account_obj, const asset_object& payout_asset_obj, int64_t expected_balance) {
|
||||
int64_t pending_balance = get_dividend_pending_payout_balance(dividend_holder_asset_object.id,
|
||||
holder_account_obj.id,
|
||||
payout_asset_obj.id);
|
||||
BOOST_CHECK_EQUAL(pending_balance, expected_balance);
|
||||
};
|
||||
|
||||
auto advance_to_next_payout_time = [&]() {
|
||||
// Advance to the next upcoming payout time
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
||||
idump((next_payout_scheduled_time));
|
||||
// generate blocks up to the next scheduled time
|
||||
generate_blocks(next_payout_scheduled_time);
|
||||
// if the scheduled time fell on a maintenance interval, then we should have paid out.
|
||||
// if not, we need to advance to the next maintenance interval to trigger the payout
|
||||
if (dividend_data.options.next_payout_time)
|
||||
{
|
||||
// we know there was a next_payout_time set when we entered this, so if
|
||||
// it has been cleared, we must have already processed payouts, no need to
|
||||
// further advance time.
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
}
|
||||
idump((db.head_block_time()));
|
||||
};
|
||||
|
||||
// the first test will be testing pending balances, so we need to hit a
|
||||
// maintenance interval that isn't the payout interval. Payout is
|
||||
// every 3 days, maintenance interval is every 1 day.
|
||||
advance_to_next_payout_time();
|
||||
|
||||
// Set up the first test, issue alice, bob, and carol, and dave each 1/4 of the total
|
||||
// supply of the core asset.
|
||||
// Then deposit 400 TEST in the distribution account, and see that they
|
||||
// each are credited 100 TEST.
|
||||
transfer( committee_account(db), alice, asset( 250000000000000 ) );
|
||||
transfer( committee_account(db), bob, asset( 250000000000000 ) );
|
||||
transfer( committee_account(db), carol, asset( 250000000000000 ) );
|
||||
transfer( committee_account(db), dave, asset( 250000000000000 ) );
|
||||
|
||||
BOOST_TEST_MESSAGE("Issuing 300 TEST to the dividend account");
|
||||
issue_asset_to_account(test_asset_object, dividend_distribution_account, 40000);
|
||||
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
|
||||
verify_pending_balance(alice, test_asset_object, 10000);
|
||||
verify_pending_balance(bob, test_asset_object, 10000);
|
||||
verify_pending_balance(carol, test_asset_object, 10000);
|
||||
verify_pending_balance(dave, test_asset_object, 10000);
|
||||
|
||||
// For the second test, issue dave more than the other two, so it's
|
||||
// alice: 1/5 CORE, bob: 1/5 CORE, carol: 1/5 CORE, dave: 2/5 CORE
|
||||
// Then deposit 500 TEST in the distribution account, and see that alice
|
||||
// bob, and carol are credited with 100 TEST, and dave gets 200 TEST
|
||||
BOOST_TEST_MESSAGE("Issuing dave twice as much of the holder asset");
|
||||
transfer( alice, dave, asset( 50000000000000 ) );
|
||||
transfer( bob, dave, asset( 50000000000000 ) );
|
||||
transfer( carol, dave, asset( 50000000000000 ) );
|
||||
issue_asset_to_account(test_asset_object, dividend_distribution_account, 50000); // 500 at two digits of precision
|
||||
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
verify_pending_balance(alice, test_asset_object, 20000);
|
||||
verify_pending_balance(bob, test_asset_object, 20000);
|
||||
verify_pending_balance(carol, test_asset_object, 20000);
|
||||
verify_pending_balance(dave, test_asset_object, 30000);
|
||||
|
||||
fc::time_point_sec old_next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
||||
advance_to_next_payout_time();
|
||||
|
||||
|
||||
BOOST_REQUIRE_MESSAGE(dividend_data.options.next_payout_time, "No new payout was scheduled");
|
||||
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time != *dividend_data.options.next_payout_time,
|
||||
"New payout was scheduled for the same time as the last payout");
|
||||
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time + *dividend_data.options.payout_interval == *dividend_data.options.next_payout_time,
|
||||
"New payout was not scheduled for the expected time");
|
||||
|
||||
auto verify_dividend_payout_operations = [&](const account_object& destination_account, const asset& expected_payout)
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Verifying the virtual op was created");
|
||||
const account_transaction_history_index& hist_idx = db.get_index_type<account_transaction_history_index>();
|
||||
auto account_history_range = hist_idx.indices().get<by_seq>().equal_range(boost::make_tuple(destination_account.id));
|
||||
BOOST_REQUIRE(account_history_range.first != account_history_range.second);
|
||||
const operation_history_object& history_object = std::prev(account_history_range.second)->operation_id(db);
|
||||
const asset_dividend_distribution_operation& distribution_operation = history_object.op.get<asset_dividend_distribution_operation>();
|
||||
BOOST_CHECK(distribution_operation.account_id == destination_account.id);
|
||||
BOOST_CHECK(std::find(distribution_operation.amounts.begin(), distribution_operation.amounts.end(), expected_payout)
|
||||
!= distribution_operation.amounts.end());
|
||||
};
|
||||
|
||||
BOOST_TEST_MESSAGE("Verifying the payouts");
|
||||
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 20000);
|
||||
verify_dividend_payout_operations(alice, asset(20000, test_asset_object.id));
|
||||
verify_pending_balance(alice, test_asset_object, 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 20000);
|
||||
verify_dividend_payout_operations(bob, asset(20000, test_asset_object.id));
|
||||
verify_pending_balance(bob, test_asset_object, 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 20000);
|
||||
verify_dividend_payout_operations(carol, asset(20000, test_asset_object.id));
|
||||
verify_pending_balance(carol, test_asset_object, 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(get_balance(dave, test_asset_object), 30000);
|
||||
verify_dividend_payout_operations(dave, asset(30000, test_asset_object.id));
|
||||
verify_pending_balance(dave, test_asset_object, 0);
|
||||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_dividend_distribution_interval )
|
||||
{
|
||||
using namespace graphene;
|
||||
try {
|
||||
INVOKE( create_dividend_uia );
|
||||
|
||||
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
|
||||
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
|
||||
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
|
||||
const account_object& alice = get_account("alice");
|
||||
const account_object& bob = get_account("bob");
|
||||
const account_object& carol = get_account("carol");
|
||||
const account_object& dave = get_account("dave");
|
||||
const account_object& frank = get_account("frank");
|
||||
const auto& test_asset_object = get_asset("TEST");
|
||||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( check_dividend_corner_cases )
|
||||
{
|
||||
using namespace graphene;
|
||||
try {
|
||||
INVOKE( create_dividend_uia );
|
||||
|
||||
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
|
||||
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
|
||||
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
|
||||
const account_object& alice = get_account("alice");
|
||||
const account_object& bob = get_account("bob");
|
||||
const account_object& carol = get_account("carol");
|
||||
const account_object& dave = get_account("dave");
|
||||
const account_object& frank = get_account("frank");
|
||||
const auto& test_asset_object = get_asset("TEST");
|
||||
|
||||
auto issue_asset_to_account = [&](const asset_object& asset_to_issue, const account_object& destination_account, int64_t amount_to_issue)
|
||||
{
|
||||
asset_issue_operation op;
|
||||
op.issuer = asset_to_issue.issuer;
|
||||
op.asset_to_issue = asset(amount_to_issue, asset_to_issue.id);
|
||||
op.issue_to_account = destination_account.id;
|
||||
trx.operations.push_back( op );
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
};
|
||||
|
||||
auto verify_pending_balance = [&](const account_object& holder_account_obj, const asset_object& payout_asset_obj, int64_t expected_balance) {
|
||||
int64_t pending_balance = get_dividend_pending_payout_balance(dividend_holder_asset_object.id,
|
||||
holder_account_obj.id,
|
||||
payout_asset_obj.id);
|
||||
BOOST_CHECK_EQUAL(pending_balance, expected_balance);
|
||||
};
|
||||
|
||||
auto reserve_asset_from_account = [&](const asset_object& asset_to_reserve, const account_object& from_account, int64_t amount_to_reserve)
|
||||
{
|
||||
asset_reserve_operation reserve_op;
|
||||
reserve_op.payer = from_account.id;
|
||||
reserve_op.amount_to_reserve = asset(amount_to_reserve, asset_to_reserve.id);
|
||||
trx.operations.push_back(reserve_op);
|
||||
set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
};
|
||||
auto advance_to_next_payout_time = [&]() {
|
||||
// Advance to the next upcoming payout time
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
||||
// generate blocks up to the next scheduled time
|
||||
generate_blocks(next_payout_scheduled_time);
|
||||
// if the scheduled time fell on a maintenance interval, then we should have paid out.
|
||||
// if not, we need to advance to the next maintenance interval to trigger the payout
|
||||
if (dividend_data.options.next_payout_time)
|
||||
{
|
||||
// we know there was a next_payout_time set when we entered this, so if
|
||||
// it has been cleared, we must have already processed payouts, no need to
|
||||
// further advance time.
|
||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
}
|
||||
};
|
||||
|
||||
// the first test will be testing pending balances, so we need to hit a
|
||||
// maintenance interval that isn't the payout interval. Payout is
|
||||
// every 3 days, maintenance interval is every 1 day.
|
||||
advance_to_next_payout_time();
|
||||
|
||||
BOOST_TEST_MESSAGE("Testing a payout interval when there are no users holding the dividend asset");
|
||||
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 0);
|
||||
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 0);
|
||||
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 0);
|
||||
issue_asset_to_account(test_asset_object, dividend_distribution_account, 1000);
|
||||
BOOST_TEST_MESSAGE("Generating blocks until next maintenance interval");
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
BOOST_TEST_MESSAGE("Verify that no pending payments were scheduled");
|
||||
verify_pending_balance(alice, test_asset_object, 0);
|
||||
verify_pending_balance(bob, test_asset_object, 0);
|
||||
verify_pending_balance(carol, test_asset_object, 0);
|
||||
advance_to_next_payout_time();
|
||||
BOOST_TEST_MESSAGE("Verify that no actual payments took place");
|
||||
verify_pending_balance(alice, test_asset_object, 0);
|
||||
verify_pending_balance(bob, test_asset_object, 0);
|
||||
verify_pending_balance(carol, test_asset_object, 0);
|
||||
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 0);
|
||||
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 0);
|
||||
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 0);
|
||||
BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, test_asset_object), 1000);
|
||||
|
||||
BOOST_TEST_MESSAGE("Now give alice a small balance and see that she takes it all");
|
||||
issue_asset_to_account(dividend_holder_asset_object, alice, 1);
|
||||
generate_block();
|
||||
BOOST_TEST_MESSAGE("Generating blocks until next maintenance interval");
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
BOOST_TEST_MESSAGE("Verify that no alice received her payment of the entire amount");
|
||||
verify_pending_balance(alice, test_asset_object, 1000);
|
||||
|
||||
// Test that we can pay out the dividend asset itself
|
||||
issue_asset_to_account(dividend_holder_asset_object, bob, 1);
|
||||
issue_asset_to_account(dividend_holder_asset_object, carol, 1);
|
||||
issue_asset_to_account(dividend_holder_asset_object, dividend_distribution_account, 300);
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL(get_balance(alice, dividend_holder_asset_object), 1);
|
||||
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 1);
|
||||
BOOST_CHECK_EQUAL(get_balance(carol, dividend_holder_asset_object), 1);
|
||||
BOOST_TEST_MESSAGE("Generating blocks until next maintenance interval");
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way
|
||||
BOOST_TEST_MESSAGE("Verify that the dividend asset was shared out");
|
||||
verify_pending_balance(alice, dividend_holder_asset_object, 100);
|
||||
verify_pending_balance(bob, dividend_holder_asset_object, 100);
|
||||
verify_pending_balance(carol, dividend_holder_asset_object, 100);
|
||||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
BOOST_AUTO_TEST_SUITE_END() // end dividend_tests suite
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cancel_limit_order_test )
|
||||
{ try {
|
||||
INVOKE( issue_uia );
|
||||
|
|
|
|||
|
|
@ -1400,7 +1400,6 @@ BOOST_AUTO_TEST_CASE( vbo_withdraw_different )
|
|||
create_op.owner = alice_id;
|
||||
create_op.amount = asset(100, stuff_id);
|
||||
create_op.policy = pinit;
|
||||
create_op.balance_type = vesting_balance_type::unspecified;
|
||||
|
||||
signed_transaction create_tx;
|
||||
create_tx.operations.push_back( create_op );
|
||||
|
|
|
|||
Loading…
Reference in a new issue