diff --git a/libraries/api/chain_api_properties.cpp b/libraries/api/chain_api_properties.cpp index 92295a6e1a..b426385f70 100644 --- a/libraries/api/chain_api_properties.cpp +++ b/libraries/api/chain_api_properties.cpp @@ -15,6 +15,11 @@ namespace golos { namespace api { create_account_delegation_time = src.create_account_delegation_time; min_delegation = src.min_delegation; } + if (db.has_hardfork(STEEMIT_HARDFORK_0_19)) { + max_referral_interest_rate = src.max_referral_interest_rate; + max_referral_term_sec = src.max_referral_term_sec; + referral_break_fee = src.referral_break_fee; + } } } } // golos::api diff --git a/libraries/api/include/golos/api/chain_api_properties.hpp b/libraries/api/include/golos/api/chain_api_properties.hpp index 7f60db0ef2..916b180509 100644 --- a/libraries/api/include/golos/api/chain_api_properties.hpp +++ b/libraries/api/include/golos/api/chain_api_properties.hpp @@ -20,6 +20,10 @@ namespace golos { namespace api { fc::optional create_account_min_delegation; fc::optional create_account_delegation_time; fc::optional min_delegation; + + fc::optional max_referral_interest_rate; + fc::optional max_referral_term_sec; + fc::optional referral_break_fee; }; } } // golos::api @@ -28,4 +32,5 @@ FC_REFLECT( (golos::api::chain_api_properties), (account_creation_fee)(maximum_block_size)(sbd_interest_rate) (create_account_min_golos_fee)(create_account_min_delegation) - (create_account_delegation_time)(min_delegation)) + (create_account_delegation_time)(min_delegation) + (max_referral_interest_rate)(max_referral_term_sec)(referral_break_fee)) diff --git a/libraries/chain/chain_properties_evaluators.cpp b/libraries/chain/chain_properties_evaluators.cpp index 0d0cca5e91..d45dc44c92 100644 --- a/libraries/chain/chain_properties_evaluators.cpp +++ b/libraries/chain/chain_properties_evaluators.cpp @@ -41,7 +41,7 @@ namespace golos { namespace chain { } struct chain_properties_convert { - using result_type = chain_properties_18; + using result_type = chain_properties_19; template result_type operator()(Props&& p) const { diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index f1af992ebd..752d301f5a 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -1867,16 +1867,16 @@ namespace golos { namespace chain { } void database::update_median_witness_props() { - const witness_schedule_object &wso = get_witness_schedule_object(); + const witness_schedule_object& wso = get_witness_schedule_object(); /// fetch all witness objects - vector active; + vector active; active.reserve(wso.num_scheduled_witnesses); for (int i = 0; i < wso.num_scheduled_witnesses; i++) { active.push_back(&get_witness(wso.current_shuffled_witnesses[i])); } - chain_properties_18 median_props; + chain_properties_19 median_props; auto calc_median = [&](auto&& param) { std::nth_element( @@ -1895,12 +1895,15 @@ namespace golos { namespace chain { calc_median(&chain_properties_18::create_account_min_delegation); calc_median(&chain_properties_18::create_account_delegation_time); calc_median(&chain_properties_18::min_delegation); + calc_median(&chain_properties_19::max_referral_interest_rate); + calc_median(&chain_properties_19::max_referral_term_sec); + calc_median(&chain_properties_19::referral_break_fee); modify(wso, [&](witness_schedule_object &_wso) { _wso.median_props = median_props; }); - modify(get_dynamic_global_properties(), [&](dynamic_global_property_object &_dgpo) { + modify(get_dynamic_global_properties(), [&](dynamic_global_property_object& _dgpo) { _dgpo.maximum_block_size = median_props.maximum_block_size; _dgpo.sbd_interest_rate = median_props.sbd_interest_rate; }); diff --git a/libraries/chain/include/golos/chain/witness_objects.hpp b/libraries/chain/include/golos/chain/witness_objects.hpp index 845da5409b..e6e6573510 100644 --- a/libraries/chain/include/golos/chain/witness_objects.hpp +++ b/libraries/chain/include/golos/chain/witness_objects.hpp @@ -17,7 +17,7 @@ namespace golos { namespace chain { using golos::protocol::asset; using golos::protocol::asset_symbol_type; - using chain_properties = golos::protocol::chain_properties_18; + using chain_properties = golos::protocol::chain_properties_19; /** * All witnesses with at least 1% net positive approval and diff --git a/libraries/protocol/include/golos/protocol/config.hpp b/libraries/protocol/include/golos/protocol/config.hpp index f297027262..b2096fbd38 100644 --- a/libraries/protocol/include/golos/protocol/config.hpp +++ b/libraries/protocol/include/golos/protocol/config.hpp @@ -112,8 +112,12 @@ #define GOLOS_CREATE_ACCOUNT_DELEGATION_TIME (fc::days(1)) #define GOLOS_MIN_DELEGATION_MULTIPLIER 10 -#define STEEMIT_MINING_REWARD asset( 666, STEEM_SYMBOL ) -#define STEEMIT_MINING_REWARD_PRE_HF_16 asset( 1000, STEEM_SYMBOL ) +#define GOLOS_DEFAULT_MAX_REFERRAL_INTEREST_RATE (10*STEEMIT_1_PERCENT) // 10% +#define GOLOS_DEFAULT_MAX_REFERRAL_TERM_SEC (60*60*24*30*6) +#define GOLOS_DEFAULT_REFERRAL_BREAK_FEE (10*STEEMIT_MIN_ACCOUNT_CREATION_FEE) + +#define STEEMIT_MINING_REWARD asset(666, STEEM_SYMBOL) +#define STEEMIT_MINING_REWARD_PRE_HF_16 asset(1000, STEEM_SYMBOL) #define STEEMIT_EQUIHASH_N 140 #define STEEMIT_EQUIHASH_K 6 @@ -121,16 +125,16 @@ #define STEEMIT_MIN_LIQUIDITY_REWARD_PERIOD_SEC (fc::seconds(60)) // 1 minute required on books to receive volume #define STEEMIT_LIQUIDITY_REWARD_PERIOD_SEC (60*60) #define STEEMIT_LIQUIDITY_REWARD_BLOCKS (STEEMIT_LIQUIDITY_REWARD_PERIOD_SEC/STEEMIT_BLOCK_INTERVAL) -#define STEEMIT_MIN_LIQUIDITY_REWARD (asset( 1000*STEEMIT_LIQUIDITY_REWARD_BLOCKS, STEEM_SYMBOL )) // Minumum reward to be paid out to liquidity providers -#define STEEMIT_MIN_CONTENT_REWARD asset( 1500, STEEM_SYMBOL ) -#define STEEMIT_MIN_CURATE_REWARD asset( 500, STEEM_SYMBOL ) +#define STEEMIT_MIN_LIQUIDITY_REWARD (asset(1000*STEEMIT_LIQUIDITY_REWARD_BLOCKS, STEEM_SYMBOL)) // Minumum reward to be paid out to liquidity providers +#define STEEMIT_MIN_CONTENT_REWARD asset(1500, STEEM_SYMBOL) +#define STEEMIT_MIN_CURATE_REWARD asset(500, STEEM_SYMBOL) #define STEEMIT_MIN_PRODUCER_REWARD STEEMIT_MINING_REWARD #define STEEMIT_MIN_PRODUCER_REWARD_PRE_HF_16 STEEMIT_MINING_REWARD_PRE_HF_16 #define STEEMIT_MIN_POW_REWARD STEEMIT_MINING_REWARD #define STEEMIT_MIN_POW_REWARD_PRE_HF_16 STEEMIT_MINING_REWARD_PRE_HF_16 -#define STEEMIT_ACTIVE_CHALLENGE_FEE asset( 2000, STEEM_SYMBOL ) -#define STEEMIT_OWNER_CHALLENGE_FEE asset( 30000, STEEM_SYMBOL ) +#define STEEMIT_ACTIVE_CHALLENGE_FEE asset(2000, STEEM_SYMBOL) +#define STEEMIT_OWNER_CHALLENGE_FEE asset(30000, STEEM_SYMBOL) #define STEEMIT_ACTIVE_CHALLENGE_COOLDOWN fc::days(1) #define STEEMIT_OWNER_CHALLENGE_COOLDOWN fc::days(1) @@ -169,7 +173,7 @@ #define STEEMIT_PRODUCER_APR_PERCENT 750 #define STEEMIT_POW_APR_PERCENT 750 -#define STEEMIT_MIN_PAYOUT_SBD (asset(20,SBD_SYMBOL)) +#define STEEMIT_MIN_PAYOUT_SBD (asset(20, SBD_SYMBOL)) #define STEEMIT_SBD_STOP_PERCENT (5*STEEMIT_1_PERCENT ) // Stop printing SBD at 5% Market Cap #define STEEMIT_SBD_START_PERCENT (2*STEEMIT_1_PERCENT) // Start reducing printing of SBD at 2% Market Cap @@ -205,7 +209,7 @@ #define STEEMIT_MAX_UNDO_HISTORY 10000 #define STEEMIT_MIN_TRANSACTION_EXPIRATION_LIMIT (STEEMIT_BLOCK_INTERVAL * 5) // 5 transactions per block -#define STEEMIT_BLOCKCHAIN_PRECISION uint64_t( 1000 ) +#define STEEMIT_BLOCKCHAIN_PRECISION uint64_t(1000) #define STEEMIT_BLOCKCHAIN_PRECISION_DIGITS 3 #define STEEMIT_MAX_INSTANCE_ID (uint64_t(-1)>>16) @@ -321,8 +325,12 @@ #define GOLOS_CREATE_ACCOUNT_DELEGATION_TIME (fc::days(30)) #define GOLOS_MIN_DELEGATION_MULTIPLIER 10 -#define STEEMIT_MINING_REWARD asset( 666, STEEM_SYMBOL ) -#define STEEMIT_MINING_REWARD_PRE_HF_16 asset( 1000, STEEM_SYMBOL ) +#define GOLOS_DEFAULT_MAX_REFERRAL_INTEREST_RATE (10*STEEMIT_1_PERCENT) // 10% +#define GOLOS_DEFAULT_MAX_REFERRAL_TERM_SEC (60*60*24*30*6) +#define GOLOS_DEFAULT_REFERRAL_BREAK_FEE (10*STEEMIT_MIN_ACCOUNT_CREATION_FEE) + +#define STEEMIT_MINING_REWARD asset(666, STEEM_SYMBOL) +#define STEEMIT_MINING_REWARD_PRE_HF_16 asset(1000, STEEM_SYMBOL) #define STEEMIT_EQUIHASH_N 140 #define STEEMIT_EQUIHASH_K 6 @@ -330,16 +338,16 @@ #define STEEMIT_MIN_LIQUIDITY_REWARD_PERIOD_SEC (fc::seconds(60)) // 1 minute required on books to receive volume #define STEEMIT_LIQUIDITY_REWARD_PERIOD_SEC (60*60) #define STEEMIT_LIQUIDITY_REWARD_BLOCKS (STEEMIT_LIQUIDITY_REWARD_PERIOD_SEC/STEEMIT_BLOCK_INTERVAL) -#define STEEMIT_MIN_LIQUIDITY_REWARD (asset( 1000*STEEMIT_LIQUIDITY_REWARD_BLOCKS, STEEM_SYMBOL )) // Minumum reward to be paid out to liquidity providers -#define STEEMIT_MIN_CONTENT_REWARD asset( 1500, STEEM_SYMBOL ) -#define STEEMIT_MIN_CURATE_REWARD asset( 500, STEEM_SYMBOL ) +#define STEEMIT_MIN_LIQUIDITY_REWARD (asset(1000*STEEMIT_LIQUIDITY_REWARD_BLOCKS, STEEM_SYMBOL)) // Minumum reward to be paid out to liquidity providers +#define STEEMIT_MIN_CONTENT_REWARD asset(1500, STEEM_SYMBOL) +#define STEEMIT_MIN_CURATE_REWARD asset(500, STEEM_SYMBOL) #define STEEMIT_MIN_PRODUCER_REWARD STEEMIT_MINING_REWARD #define STEEMIT_MIN_PRODUCER_REWARD_PRE_HF_16 STEEMIT_MINING_REWARD_PRE_HF_16 #define STEEMIT_MIN_POW_REWARD STEEMIT_MINING_REWARD #define STEEMIT_MIN_POW_REWARD_PRE_HF_16 STEEMIT_MINING_REWARD_PRE_HF_16 -#define STEEMIT_ACTIVE_CHALLENGE_FEE asset( 2000, STEEM_SYMBOL ) -#define STEEMIT_OWNER_CHALLENGE_FEE asset( 30000, STEEM_SYMBOL ) +#define STEEMIT_ACTIVE_CHALLENGE_FEE asset(2000, STEEM_SYMBOL) +#define STEEMIT_OWNER_CHALLENGE_FEE asset(30000, STEEM_SYMBOL) #define STEEMIT_ACTIVE_CHALLENGE_COOLDOWN fc::days(1) #define STEEMIT_OWNER_CHALLENGE_COOLDOWN fc::days(1) @@ -414,7 +422,7 @@ #define STEEMIT_MAX_UNDO_HISTORY 10000 #define STEEMIT_MIN_TRANSACTION_EXPIRATION_LIMIT (STEEMIT_BLOCK_INTERVAL * 5) // 5 transactions per block -#define STEEMIT_BLOCKCHAIN_PRECISION uint64_t( 1000 ) +#define STEEMIT_BLOCKCHAIN_PRECISION uint64_t(1000) #define STEEMIT_BLOCKCHAIN_PRECISION_DIGITS 3 #define STEEMIT_MAX_INSTANCE_ID (uint64_t(-1)>>16) diff --git a/libraries/protocol/include/golos/protocol/steem_operations.hpp b/libraries/protocol/include/golos/protocol/steem_operations.hpp index 0a131cc642..d85c5eec83 100644 --- a/libraries/protocol/include/golos/protocol/steem_operations.hpp +++ b/libraries/protocol/include/golos/protocol/steem_operations.hpp @@ -496,6 +496,38 @@ namespace golos { namespace protocol { chain_properties_18& operator=(const chain_properties_18&) = default; }; + /** + * Users can invite referrals, and they will pay some percent of rewards to their referrers. + * Referral can break paying for some fee. + */ + struct chain_properties_19: public chain_properties_18 { + + /** + * Maximum percent of referral deductions + */ + uint16_t max_referral_interest_rate = GOLOS_DEFAULT_MAX_REFERRAL_INTEREST_RATE; + + /** + * Maximum term of referral deductions + */ + uint32_t max_referral_term_sec = GOLOS_DEFAULT_MAX_REFERRAL_TERM_SEC; + + /** + * Fee for breaking referral deductions by referral + */ + asset referral_break_fee = + asset(GOLOS_DEFAULT_REFERRAL_BREAK_FEE, STEEM_SYMBOL); + + void validate() const; + + chain_properties_19& operator=(const chain_properties_17& src) { + chain_properties_18::operator=(src); + return *this; + } + + chain_properties_19& operator=(const chain_properties_19&) = default; + }; + inline chain_properties_17& chain_properties_17::operator=(const chain_properties_18& src) { account_creation_fee = src.account_creation_fee; maximum_block_size = src.maximum_block_size; @@ -505,7 +537,8 @@ namespace golos { namespace protocol { using versioned_chain_properties = fc::static_variant< chain_properties_17, - chain_properties_18 + chain_properties_18, + chain_properties_19 >; /** @@ -1141,9 +1174,12 @@ FC_REFLECT( (golos::protocol::chain_properties_17), (account_creation_fee)(maximum_block_size)(sbd_interest_rate)) FC_REFLECT_DERIVED( - (golos::protocol::chain_properties_18),((golos::protocol::chain_properties_17)), + (golos::protocol::chain_properties_18), ((golos::protocol::chain_properties_17)), (create_account_min_golos_fee)(create_account_min_delegation) (create_account_delegation_time)(min_delegation)) +FC_REFLECT_DERIVED( + (golos::protocol::chain_properties_19), ((golos::protocol::chain_properties_18)), + (max_referral_interest_rate)(max_referral_term_sec)(referral_break_fee)) FC_REFLECT_TYPENAME((golos::protocol::versioned_chain_properties)) diff --git a/libraries/protocol/include/golos/protocol/validate_helper.hpp b/libraries/protocol/include/golos/protocol/validate_helper.hpp index 0a0898c07b..73ed6e4165 100644 --- a/libraries/protocol/include/golos/protocol/validate_helper.hpp +++ b/libraries/protocol/include/golos/protocol/validate_helper.hpp @@ -39,7 +39,7 @@ #define GOLOS_CHECK_VALUE_GE(F, X) GOLOS_CHECK_VALUE_I(F, >=, X) #define GOLOS_CHECK_VALUE_LE(F, X) GOLOS_CHECK_VALUE_I(F, <=, X) #define GOLOS_CHECK_VALUE_LEGE(F, L, H) \ - GOLOS_CHECK_VALUE((L) <= F && F <= (H) , MUST_BE(F, "between " FC_STRINGIZE(L) " and" FC_STRINGIZE(H))) + GOLOS_CHECK_VALUE((L) <= F && F <= (H), MUST_BE(F, "between " FC_STRINGIZE(L) " and " FC_STRINGIZE(H))) // check asset type #define GOLOS_CHECK_ASSET_TYPE(X, NAME) GOLOS_CHECK_ASSET_##NAME(X); diff --git a/libraries/protocol/steem_operations.cpp b/libraries/protocol/steem_operations.cpp index f82f18fcdc..0604319883 100644 --- a/libraries/protocol/steem_operations.cpp +++ b/libraries/protocol/steem_operations.cpp @@ -226,6 +226,13 @@ namespace golos { namespace protocol { (GOLOS_CREATE_ACCOUNT_DELEGATION_TIME).to_seconds() / 2); } + void chain_properties_19::validate() const { + chain_properties_18::validate(); + GOLOS_CHECK_VALUE_LE(max_referral_interest_rate, STEEMIT_100_PERCENT); + GOLOS_CHECK_VALUE_LE(max_referral_term_sec, 60*60*24*30*12); + GOLOS_CHECK_VALUE_LEGE(referral_break_fee, 1*account_creation_fee, 10*account_creation_fee); + } + void witness_update_operation::validate() const { GOLOS_CHECK_PARAM_ACCOUNT(owner); GOLOS_CHECK_PARAM(url, { diff --git a/libraries/wallet/include/golos/wallet/wallet.hpp b/libraries/wallet/include/golos/wallet/wallet.hpp index 0a93512ca3..36d23ccc9c 100644 --- a/libraries/wallet/include/golos/wallet/wallet.hpp +++ b/libraries/wallet/include/golos/wallet/wallet.hpp @@ -44,6 +44,10 @@ namespace golos { namespace wallet { fc::optional create_account_min_delegation; fc::optional create_account_delegation_time; fc::optional min_delegation; + + fc::optional max_referral_interest_rate; + fc::optional max_referral_term_sec; + fc::optional referral_break_fee; }; struct optional_private_box_query { @@ -1488,7 +1492,8 @@ FC_REFLECT( FC_REFLECT((golos::wallet::optional_chain_props), (account_creation_fee)(maximum_block_size)(sbd_interest_rate) (create_account_min_golos_fee)(create_account_min_delegation) - (create_account_delegation_time)(min_delegation)) + (create_account_delegation_time)(min_delegation) + (max_referral_interest_rate)(max_referral_term_sec)(referral_break_fee)) FC_REFLECT( (golos::wallet::message_body), diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 631c810f06..b26d9557f8 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -326,6 +326,11 @@ namespace golos { namespace wallet { result["create_account_delegation_time"] = median_props.create_account_delegation_time; result["min_delegation"] = median_props.min_delegation; } + if (hf >= hardfork_version(0, STEEMIT_HARDFORK_0_19)) { + result["max_referral_interest_rate"] = median_props.max_referral_interest_rate; + result["max_referral_term_sec"] = median_props.max_referral_term_sec; + result["referral_break_fee"] = median_props.referral_break_fee; + } return result; } @@ -2186,6 +2191,9 @@ fc::ecc::private_key wallet_api::derive_private_key(const std::string& prefix_st SET_PROP(create_account_min_delegation); SET_PROP(create_account_delegation_time); SET_PROP(min_delegation); + SET_PROP(max_referral_interest_rate); + SET_PROP(max_referral_term_sec); + SET_PROP(referral_break_fee); #undef SET_PROP op.owner = witness_account_name;