diff --git a/contracts/eosio.system/include/eosio.system/eosio.system.hpp b/contracts/eosio.system/include/eosio.system/eosio.system.hpp index 129b803..52056b0 100644 --- a/contracts/eosio.system/include/eosio.system/eosio.system.hpp +++ b/contracts/eosio.system/include/eosio.system/eosio.system.hpp @@ -551,6 +551,14 @@ namespace eosiosystem { typedef eosio::multi_index< "rexqueue"_n, rex_order, indexed_by<"bytime"_n, const_mem_fun>> rex_order_table; + struct [[eosio::table("rexmaturity"),eosio::contract("eosio.system")]] rex_maturity { + uint32_t num_of_maturity_buckets = 5; + bool sell_matured_rex = false; + bool buy_rex_to_savings = false; + }; + + typedef eosio::singleton<"rexmaturity"_n, rex_maturity> rex_maturity_singleton; + struct rex_order_outcome { bool success; asset proceeds; @@ -735,6 +743,7 @@ namespace eosiosystem { rex_fund_table _rexfunds; rex_balance_table _rexbalance; rex_order_table _rexorders; + rex_maturity_singleton _rexmaturity; public: static constexpr eosio::name active_permission{"active"_n}; @@ -922,12 +931,9 @@ namespace eosiosystem { * @param from - owner account name, * @param amount - amount of tokens taken out of 'from' REX fund. * - * @pre A voting requirement must be satisfied before action can be executed. - * @pre User must vote for at least 21 producers or delegate vote to proxy before buying REX. - * * @post User votes are updated following this action. * @post Tokens used in purchase are added to user's voting power. - * @post Bought REX cannot be sold before 4 days counting from end of day of purchase. + * @post Bought REX cannot be sold before {num_of_maturity_buckets} days counting from end of day of purchase. */ [[eosio::action]] void buyrex( const name& from, const asset& amount ); @@ -941,12 +947,9 @@ namespace eosiosystem { * @param from_net - amount of tokens to be unstaked from NET bandwidth and used for REX purchase, * @param from_cpu - amount of tokens to be unstaked from CPU bandwidth and used for REX purchase. * - * @pre A voting requirement must be satisfied before action can be executed. - * @pre User must vote for at least 21 producers or delegate vote to proxy before buying REX. - * * @post User votes are updated following this action. * @post Tokens used in purchase are added to user's voting power. - * @post Bought REX cannot be sold before 4 days counting from end of day of purchase. + * @post Bought REX cannot be sold before {num_of_maturity_buckets} days counting from end of day of purchase. */ [[eosio::action]] void unstaketorex( const name& owner, const name& receiver, const asset& from_net, const asset& from_cpu ); @@ -1075,7 +1078,7 @@ namespace eosiosystem { void rexexec( const name& user, uint16_t max ); /** - * Consolidate action, consolidates REX maturity buckets into one bucket that can be sold after 4 days + * Consolidate action, consolidates REX maturity buckets into one bucket that can be sold after {num_of_maturity_buckets} days * starting from the end of the day. * * @param owner - REX owner account name. @@ -1087,7 +1090,7 @@ namespace eosiosystem { * Mvtosavings action, moves a specified amount of REX into savings bucket. REX savings bucket * never matures. In order for it to be sold, it has to be moved explicitly * out of that bucket. Then the moved amount will have the regular maturity - * period of 4 days starting from the end of the day. + * period of {num_of_maturity_buckets} days starting from the end of the day. * * @param owner - REX owner account name. * @param rex - amount of REX to be moved. @@ -1097,7 +1100,7 @@ namespace eosiosystem { /** * Mvfrsavings action, moves a specified amount of REX out of savings bucket. The moved amount - * will have the regular REX maturity period of 4 days. + * will have the regular REX maturity period of {num_of_maturity_buckets} days. * * @param owner - REX owner account name. * @param rex - amount of REX to be moved. @@ -1119,6 +1122,18 @@ namespace eosiosystem { [[eosio::action]] void closerex( const name& owner ); + /** + * Facilitates the modification of REX maturity buckets + * + * @param num_of_maturity_buckets - used to calculate maturity time of purchase REX tokens from end of the day UTC. + * @param sell_matured_rex - if true, matured REX is sold immediately. + * https://github.com/eosnetworkfoundation/eos-system-contracts/issues/134 + * @param buy_rex_to_savings - if true, buying REX is moved immediately to REX savings. + * https://github.com/eosnetworkfoundation/eos-system-contracts/issues/135 + */ + [[eosio::action]] + void setrexmature(const std::optional num_of_maturity_buckets, const std::optional sell_matured_rex, const std::optional buy_rex_to_savings ); + /** * Donatetorex action, donates funds to REX, increases REX pool return buckets * Executes inline transfer from payer to system contract of tokens will be executed. @@ -1672,8 +1687,6 @@ namespace eosiosystem { void runrex( uint16_t max ); void update_rex_pool(); void update_resource_limits( const name& from, const name& receiver, int64_t delta_net, int64_t delta_cpu ); - void check_voting_requirement( const name& owner, - const char* error_msg = "must vote for at least 21 producers or for a proxy before buying REX" )const; rex_order_outcome fill_rex_order( const rex_balance_table::const_iterator& bitr, const asset& rex ); asset update_rex_account( const name& owner, const asset& proceeds, const asset& unstake_quant, bool force_vote_update = false ); template @@ -1685,16 +1698,19 @@ namespace eosiosystem { void transfer_from_fund( const name& owner, const asset& amount ); void transfer_to_fund( const name& owner, const asset& amount ); bool rex_loans_available()const; - static time_point_sec get_rex_maturity(); + static time_point_sec get_rex_maturity(const name& system_account_name = "eosio"_n ); asset add_to_rex_balance( const name& owner, const asset& payment, const asset& rex_received ); asset add_to_rex_pool( const asset& payment ); void add_to_rex_return_pool( const asset& fee ); void process_rex_maturities( const rex_balance_table::const_iterator& bitr ); + void process_sell_matured_rex( const name owner ); + void process_buy_rex_to_savings( const name owner, const asset rex ); void consolidate_rex_balance( const rex_balance_table::const_iterator& bitr, const asset& rex_in_sell_order ); int64_t read_rex_savings( const rex_balance_table::const_iterator& bitr ); void put_rex_savings( const rex_balance_table::const_iterator& bitr, int64_t rex ); void update_rex_stake( const name& voter ); + void sell_rex( const name& from, const asset& rex ); void add_loan_to_rex_pool( const asset& payment, int64_t rented_tokens, bool new_loan ); void remove_loan_from_rex_pool( const rex_loan& loan ); diff --git a/contracts/eosio.system/ricardian/eosio.system.contracts.md.in b/contracts/eosio.system/ricardian/eosio.system.contracts.md.in index dd5c710..396f4be 100644 --- a/contracts/eosio.system/ricardian/eosio.system.contracts.md.in +++ b/contracts/eosio.system/ricardian/eosio.system.contracts.md.in @@ -413,6 +413,27 @@ icon: @ICON_BASE_URL@/@REX_ICON_URI@ Performs REX maintenance by processing a maximum of {{max}} REX sell orders and expired loans. Any account can execute this action. +

setrexmature

+ +--- +spec_version: "0.2.0" +title: Set REX Maturity Settings +summary: 'Sets the options for REX maturity buckets' +icon: @ICON_BASE_URL@/@REX_ICON_URI@ +--- + +{{#if num_of_maturity_buckets}} + Sets the numbers of maturity buckets to '{{num_of_maturity_buckets}}' +{{/if}} + +{{#if sell_matured_rex}} + Sets whether or not to immediately sell matured REX to '{{sell_matured_rex}}' +{{/if}} + +{{#if buy_rex_to_savings}} + Sets whether or not to immediately move purchased REX to savings to '{{buy_rex_to_savings}}' +{{/if}} +

rmvproducer

--- @@ -489,9 +510,15 @@ summary: '{{nowrap from}} sells {{nowrap rex}} tokens' icon: @ICON_BASE_URL@/@REX_ICON_URI@ --- -{{from}} initiates a sell order to sell {{rex}} tokens at the market exchange rate during the time at which the order is ultimately executed. If {{from}} already has an open sell order in the sell queue, {{rex}} will be added to the amount of the sell order without change the position of the sell order within the queue. Once the sell order is executed, proceeds are added to {{from}}’s REX fund, the value of sold REX tokens is deducted from {{from}}’s vote stake, and votes are updated accordingly. +The 'rex' parameter no longer has an effect. + +{{from}} initiates a sell order to sell all of their matured REX tokens at the market exchange rate during the time at which the order is ultimately executed. +If {{from}} already has an open sell order in the sell queue, {{rex}} will be added to the amount of the sell order without change the position of the sell order within the queue. +Once the sell order is executed, proceeds are added to {{from}}’s REX fund, the value of sold REX tokens is deducted from {{from}}’s vote stake, and votes are updated accordingly. -Depending on the market conditions, it may not be possible to fill the entire sell order immediately. In such a case, the sell order is added to the back of a sell queue. A sell order at the front of the sell queue will automatically be executed when the market conditions allow for the entire order to be filled. Regardless of the market conditions, the system is designed to execute this sell order within 30 days. {{from}} can cancel the order at any time before it is filled using the cnclrexorder action. +Depending on the market conditions, it may not be possible to fill the entire sell order immediately. In such a case, the sell order is added to the back of a sell queue. +A sell order at the front of the sell queue will automatically be executed when the market conditions allow for the entire order to be filled. Regardless of the market conditions, +the system is designed to execute this sell order within 30 days. {{from}} can cancel the order at any time before it is filled using the cnclrexorder action.

setabi

diff --git a/contracts/eosio.system/src/eosio.system.cpp b/contracts/eosio.system/src/eosio.system.cpp index a566b01..92a3f0b 100644 --- a/contracts/eosio.system/src/eosio.system.cpp +++ b/contracts/eosio.system/src/eosio.system.cpp @@ -31,7 +31,8 @@ namespace eosiosystem { _rexretbuckets(get_self(), get_self().value), _rexfunds(get_self(), get_self().value), _rexbalance(get_self(), get_self().value), - _rexorders(get_self(), get_self().value) + _rexorders(get_self(), get_self().value), + _rexmaturity(get_self(), get_self().value) { _gstate = _global.exists() ? _global.get() : get_default_parameters(); _gstate2 = _global2.exists() ? _global2.get() : eosio_global_state2{}; diff --git a/contracts/eosio.system/src/rex.cpp b/contracts/eosio.system/src/rex.cpp index 804233f..43bbac5 100644 --- a/contracts/eosio.system/src/rex.cpp +++ b/contracts/eosio.system/src/rex.cpp @@ -8,6 +8,21 @@ namespace eosiosystem { using eosio::token; using eosio::seconds; + void system_contract::setrexmature(const std::optional num_of_maturity_buckets, const std::optional sell_matured_rex, const std::optional buy_rex_to_savings ) + { + require_auth(get_self()); + + auto state = _rexmaturity.get_or_default(); + + check(*num_of_maturity_buckets > 0, "num_of_maturity_buckets must be positive"); + check(*num_of_maturity_buckets <= 30, "num_of_maturity_buckets must be less than or equal to 30"); + + if ( num_of_maturity_buckets ) state.num_of_maturity_buckets = *num_of_maturity_buckets; + if ( sell_matured_rex ) state.sell_matured_rex = *sell_matured_rex; + if ( buy_rex_to_savings ) state.buy_rex_to_savings = *buy_rex_to_savings; + _rexmaturity.set(state, get_self()); + } + void system_contract::deposit( const name& owner, const asset& amount ) { require_auth( owner ); @@ -43,12 +58,15 @@ namespace eosiosystem { check( amount.symbol == core_symbol(), "asset must be core token" ); check( 0 < amount.amount, "must use positive amount" ); - check_voting_requirement( from ); transfer_from_fund( from, amount ); const asset rex_received = add_to_rex_pool( amount ); const asset delta_rex_stake = add_to_rex_balance( from, amount, rex_received ); runrex(2); update_rex_account( from, asset( 0, core_symbol() ), delta_rex_stake ); + + process_buy_rex_to_savings( from, rex_received ); + process_sell_matured_rex( from ); + // dummy action added so that amount of REX tokens purchased shows up in action trace rex_results::buyresult_action buyrex_act( rex_account, std::vector{ } ); buyrex_act.send( rex_received ); @@ -61,7 +79,6 @@ namespace eosiosystem { check( from_net.symbol == core_symbol() && from_cpu.symbol == core_symbol(), "asset must be core token" ); check( (0 <= from_net.amount) && (0 <= from_cpu.amount) && (0 < from_net.amount || 0 < from_cpu.amount), "must unstake a positive amount to buy rex" ); - check_voting_requirement( owner ); { del_bandwidth_table dbw_table( get_self(), owner.value ); @@ -89,6 +106,10 @@ namespace eosiosystem { auto rex_stake_delta = add_to_rex_balance( owner, payment, rex_received ); runrex(2); update_rex_account( owner, asset( 0, core_symbol() ), rex_stake_delta - payment, true ); + + process_buy_rex_to_savings( owner, rex_received ); + process_sell_matured_rex( owner ); + // dummy action added so that amount of REX tokens purchased shows up in action trace rex_results::buyresult_action buyrex_act( rex_account, std::vector{ } ); buyrex_act.send( rex_received ); @@ -97,7 +118,12 @@ namespace eosiosystem { void system_contract::sellrex( const name& from, const asset& rex ) { require_auth( from ); + sell_rex( from, rex ); + process_sell_matured_rex( from ); + } + void system_contract::sell_rex( const name& from, const asset& rex ) + { runrex(2); auto bitr = _rexbalance.require_find( from.value, "user must first buyrex" ); @@ -431,19 +457,6 @@ namespace eosiosystem { } } - /** - * @brief Checks if account satisfies voting requirement (voting for a proxy or 21 producers) - * for buying REX - * - * @param owner - account buying or already holding REX tokens - * @err_msg - error message - */ - void system_contract::check_voting_requirement( const name& owner, const char* error_msg )const - { - auto vitr = _voters.find( owner.value ); - check( vitr != _voters.end() && ( vitr->proxy || 21 <= vitr->producers.size() ), error_msg ); - } - /** * @brief Checks if CPU and Network loans are available * @@ -932,14 +945,15 @@ namespace eosiosystem { } /** - * @brief Calculates maturity time of purchased REX tokens which is 4 days from end + * @brief Calculates maturity time of purchased REX tokens which is {num_of_maturity_buckets} days from end * of the day UTC * * @return time_point_sec */ - time_point_sec system_contract::get_rex_maturity() + time_point_sec system_contract::get_rex_maturity( const name& system_account_name ) { - const uint32_t num_of_maturity_buckets = 5; + rex_maturity_singleton _rexmaturity(system_account_name, system_account_name.value); + const uint32_t num_of_maturity_buckets = _rexmaturity.get_or_default().num_of_maturity_buckets; // default 5 static const uint32_t now = current_time_point().sec_since_epoch(); static const uint32_t r = now % seconds_per_day; static const time_point_sec rms{ now - r + num_of_maturity_buckets * seconds_per_day }; @@ -962,6 +976,38 @@ namespace eosiosystem { }); } + /** + * @brief Sells matured REX tokens + * https://github.com/eosnetworkfoundation/eos-system-contracts/issues/134 + * + * @param owner - owner account name + */ + void system_contract::process_sell_matured_rex( const name owner ) + { + const auto rex_maturity_state = _rexmaturity.get_or_default(); + if ( rex_maturity_state.sell_matured_rex == false ) return; // skip selling matured REX + + const auto itr = _rexbalance.find( owner.value ); + if ( itr->matured_rex > 0 ) { + sell_rex(owner, asset(itr->matured_rex, rex_symbol)); + } + } + + /** + * @brief Move new REX tokens to savings + * https://github.com/eosnetworkfoundation/eos-system-contracts/issues/135 + * + * @param owner - owner account name + * @param rex - amount of REX tokens to be moved to savings + */ + void system_contract::process_buy_rex_to_savings( const name owner, const asset rex ) + { + const auto rex_maturity_state = _rexmaturity.get_or_default(); + if ( rex_maturity_state.buy_rex_to_savings && rex.amount > 0 ) { + mvtosavings( owner, rex ); + } + } + /** * @brief Consolidates REX maturity buckets into one * diff --git a/contracts/eosio.system/src/voting.cpp b/contracts/eosio.system/src/voting.cpp index 9f47d23..d360ef8 100644 --- a/contracts/eosio.system/src/voting.cpp +++ b/contracts/eosio.system/src/voting.cpp @@ -208,10 +208,6 @@ namespace eosiosystem { vote_stake_updater( voter_name ); update_votes( voter_name, proxy, producers, true ); - auto rex_itr = _rexbalance.find( voter_name.value ); - if( rex_itr != _rexbalance.end() && rex_itr->rex_balance.amount > 0 ) { - check_voting_requirement( voter_name, "voter holding REX tokens must vote for at least 21 producers or for a proxy" ); - } } void system_contract::voteupdate( const name& voter_name ) { diff --git a/tests/eosio.system_rex_matured_tests.cpp b/tests/eosio.system_rex_matured_tests.cpp new file mode 100644 index 0000000..c7699bc --- /dev/null +++ b/tests/eosio.system_rex_matured_tests.cpp @@ -0,0 +1,103 @@ +#include + +#include "eosio.system_tester.hpp" + +using namespace eosio_system; + +BOOST_AUTO_TEST_SUITE(eosio_system_rex_tests) + +bool within_error(int64_t a, int64_t b, int64_t err) { return std::abs(a - b) <= err; }; +bool within_one(int64_t a, int64_t b) { return within_error(a, b, 1); } + +BOOST_FIXTURE_TEST_CASE( buy_sell_matured_rex, eosio_system_tester ) try { + // @param num_of_maturity_buckets - used to calculate maturity time of purchase REX tokens from end of the day UTC. + // @param sell_matured_rex - if true, matured REX is sold immediately. + // @param buy_rex_to_savings - if true, buying REX is moved immediately to REX savings. + // + // https://github.com/eosnetworkfoundation/eos-system-contracts/issues/132 + // https://github.com/eosnetworkfoundation/eos-system-contracts/issues/134 + // https://github.com/eosnetworkfoundation/eos-system-contracts/issues/135 + + // setup accounts + const int64_t ratio = 10000; + const asset init_rent = core_sym::from_string("20000.0000"); + const asset init_balance = core_sym::from_string("1000.0000"); + const std::vector accounts = { "alice"_n, "bob"_n, "charly"_n, "david"_n, "mark"_n }; + account_name alice = accounts[0], bob = accounts[1], charly = accounts[2], david = accounts[3], mark = accounts[4]; + setup_rex_accounts( accounts, init_balance ); + + + // 1. set `num_of_maturity_buckets=21` to test increasing maturity time of buying REX tokens. + BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, false, false ) ); + BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( alice, core_sym::from_string("2.5000") ) ); + produce_blocks(2); + produce_block(fc::days(5)); + BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( alice, asset::from_string("25000.0000 REX") ) ); + produce_block(fc::days(16)); + + BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_sellrex_result( alice, asset::from_string("25000.0000 REX") ) ); + BOOST_REQUIRE_EQUAL( success(), buyrex( alice, core_sym::from_string("13.0000") ) ); + BOOST_REQUIRE_EQUAL( core_sym::from_string("13.0000"), get_rex_vote_stake( alice ) ); + BOOST_REQUIRE_EQUAL( success(), buyrex( alice, core_sym::from_string("17.0000") ) ); + BOOST_REQUIRE_EQUAL( core_sym::from_string("30.0000"), get_rex_vote_stake( alice ) ); + BOOST_REQUIRE_EQUAL( core_sym::from_string("970.0000"), get_rex_fund(alice) ); + BOOST_REQUIRE_EQUAL( get_rex_balance(alice).get_amount(), ratio * asset::from_string("30.0000 REX").get_amount() ); + auto rex_pool = get_rex_pool(); + BOOST_REQUIRE_EQUAL( core_sym::from_string("30.0000"), rex_pool["total_lendable"].as() ); + BOOST_REQUIRE_EQUAL( core_sym::from_string("30.0000"), rex_pool["total_unlent"].as() ); + BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), rex_pool["total_lent"].as() ); + BOOST_REQUIRE_EQUAL( init_rent, rex_pool["total_rent"].as() ); + BOOST_REQUIRE_EQUAL( get_rex_balance(alice), rex_pool["total_rex"].as() ); + + // 2. set `sell_matured_rex=true` and `buy_rex_to_savings=false` to test buying REX without moving it to REX savings + BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, true, false ) ); + BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( bob, core_sym::from_string("2.5000") ) ); + produce_blocks(2); + produce_block(fc::days(5)); + BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( bob, asset::from_string("25000.0000 REX") ) ); + produce_block(fc::days(16)); + BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_rex_vote_stake( bob ) ); + BOOST_REQUIRE_EQUAL( asset::from_string("10000.0000 REX"), get_buyrex_result( bob, core_sym::from_string("1.0000") ) ); // will also triggers sell matured REX + BOOST_REQUIRE_EQUAL( core_sym::from_string("1.0000"), get_rex_vote_stake( bob ) ); + + // 3. set `sell_matured_rex=false` and `buy_rex_to_savings=true` to test selling matured REX + BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, false, true ) ); + BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( charly, core_sym::from_string("2.5000") ) ); // when buying REX, it will automatically be moved to REX savings + BOOST_REQUIRE_EQUAL( success(), mvfrsavings( charly, asset::from_string("25000.0000 REX") ) ); // move REX from savings to initiate matured REX unstaking process + produce_blocks(2); + produce_block(fc::days(5)); + BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( charly, asset::from_string("25000.0000 REX") ) ); + produce_block(fc::days(16)); + BOOST_REQUIRE_EQUAL( success(), updaterex( charly ) ); // triggers sell matured REX (any REX action causes sell matured REX) + BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_sellrex_result( charly, asset::from_string("25000.0000 REX") ) ); + BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_rex_vote_stake( charly ) ); + BOOST_REQUIRE_EQUAL( init_balance, get_rex_fund( charly ) ); + + // 4. legacy holders with matured REX + BOOST_REQUIRE_EQUAL( success(), setrexmature( 5, false, false ) ); + BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( david, core_sym::from_string("2.5000") ) ); // legacy 5 days maturity + BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( mark, core_sym::from_string("2.5000") ) ); + produce_blocks(2); + produce_block(fc::days(5)); + BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, true, true ) ); + BOOST_REQUIRE_EQUAL( asset::from_string("10000.0000 REX"), get_buyrex_result( david, core_sym::from_string("1.0000") ) ); // new 21 days maturity & triggers sell matured REX + + // 4.1. Test selling less than all their matured rex, and having all of their already matured rex sold regardless + BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_sellrex_result( mark, asset::from_string("1.0000 REX") ) ); + + BOOST_REQUIRE_EQUAL( success(), mvfrsavings( david, asset::from_string("10000.0000 REX") ) ); // must move REX from savings to initiate matured REX unstaking process + BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( david, asset::from_string("25000.0000 REX") ) ); // already sold when previously buying REX + produce_blocks(2); + produce_block(fc::days(5)); + BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( david, asset::from_string("10000.0000 REX") ) ); // 21 day REX not matured yet + produce_blocks(2); + produce_block(fc::days(21)); + BOOST_REQUIRE_EQUAL( core_sym::from_string("1.0000"), get_sellrex_result( david, asset::from_string("10000.0000 REX") ) ); + BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_rex_vote_stake( david ) ); + BOOST_REQUIRE_EQUAL( init_balance, get_rex_fund( david ) ); + + + +} FC_LOG_AND_RETHROW() + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/eosio.system_tester.hpp b/tests/eosio.system_tester.hpp index 65142e6..7b6ca8d 100644 --- a/tests/eosio.system_tester.hpp +++ b/tests/eosio.system_tester.hpp @@ -796,13 +796,14 @@ class eosio_system_tester : public TESTER { asset get_sellrex_result( const account_name& from, const asset& rex ) { auto trace = base_tester::push_action( config::system_account_name, "sellrex"_n, from, mvo()("from", from)("rex", rex) ); - asset proceeds; + asset proceeds = core_sym::from_string("0.0000"); for ( size_t i = 0; i < trace->action_traces.size(); ++i ) { if ( trace->action_traces[i].act.name == "sellresult"_n ) { + asset _action_proceeds; fc::raw::unpack( trace->action_traces[i].act.data.data(), trace->action_traces[i].act.data.size(), - proceeds ); - return proceeds; + _action_proceeds ); + proceeds += _action_proceeds; } } return proceeds; @@ -930,6 +931,10 @@ class eosio_system_tester : public TESTER { return push_action( name(owner), "closerex"_n, mvo()("owner", owner) ); } + action_result setrexmature(const std::optional num_of_maturity_buckets, const std::optional sell_matured_rex, const std::optional buy_rex_to_savings ) { + return push_action( "eosio"_n, "setrexmature"_n, mvo()("num_of_maturity_buckets", num_of_maturity_buckets)("sell_matured_rex", sell_matured_rex)("buy_rex_to_savings", buy_rex_to_savings) ); + } + action_result donatetorex( const account_name& payer, const asset& quantity, const std::string& memo ) { return push_action( name(payer), "donatetorex"_n, mvo() ("payer", payer) diff --git a/tests/eosio.system_tests.cpp b/tests/eosio.system_tests.cpp index 04b666c..d8947c8 100644 --- a/tests/eosio.system_tests.cpp +++ b/tests/eosio.system_tests.cpp @@ -4201,8 +4201,6 @@ BOOST_FIXTURE_TEST_CASE( unstake_buy_rex, eosio_system_tester, * boost::unit_tes BOOST_REQUIRE_EQUAL( get_net_limit( alice ), init_net_limit + net_stake.get_amount() ); BOOST_REQUIRE_EQUAL( success(), vote( alice, std::vector(producer_names.begin(), producer_names.begin() + 20) ) ); - BOOST_REQUIRE_EQUAL( wasm_assert_msg("must vote for at least 21 producers or for a proxy before buying REX"), - unstaketorex( alice, alice, net_stake, cpu_stake ) ); BOOST_REQUIRE_EQUAL( success(), vote( alice, std::vector(producer_names.begin(), producer_names.begin() + 21) ) ); const asset init_eosio_stake_balance = get_balance( "eosio.stake"_n ); @@ -5224,8 +5222,6 @@ BOOST_FIXTURE_TEST_CASE( update_rex, eosio_system_tester, * boost::unit_test::to } } - BOOST_REQUIRE_EQUAL( wasm_assert_msg("voter holding REX tokens must vote for at least 21 producers or for a proxy"), - vote( alice, std::vector(producer_names.begin(), producer_names.begin() + 20) ) ); BOOST_REQUIRE_EQUAL( success(), vote( alice, std::vector(producer_names.begin(), producer_names.begin() + 21) ) ); @@ -5261,8 +5257,6 @@ BOOST_FIXTURE_TEST_CASE( update_rex, eosio_system_tester, * boost::unit_test::to BOOST_REQUIRE_EQUAL( success(), sellrex( alice, get_rex_balance( alice ) ) ); BOOST_REQUIRE_EQUAL( 0, get_rex_balance( alice ).get_amount() ); BOOST_REQUIRE_EQUAL( success(), vote( alice, { producer_names[0], producer_names[4] } ) ); - BOOST_REQUIRE_EQUAL( wasm_assert_msg("must vote for at least 21 producers or for a proxy before buying REX"), - buyrex( alice, core_sym::from_string("1.0000") ) ); } FC_LOG_AND_RETHROW() @@ -5591,9 +5585,6 @@ BOOST_FIXTURE_TEST_CASE( b1_vesting, eosio_system_tester ) try { const asset oneToken = core_sym::from_string("1.0000"); const asset zero = core_sym::from_string("0.0000"); - // Can't use rex - BOOST_REQUIRE_EQUAL( wasm_assert_msg("must vote for at least 21 producers or for a proxy before buying REX"), - unstaketorex( b1, b1, vested, zero ) ); BOOST_REQUIRE_EQUAL( error("missing authority of eosio"), vote( b1, { }, "proxyaccount"_n ) ); // Can't take what isn't vested