Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Commit

Permalink
Merge pull request #418 from EOSIO/merge-release-1.8.3-to-master
Browse files Browse the repository at this point in the history
Version 1.8.3
  • Loading branch information
arhag authored Dec 16, 2019
2 parents 79f63ad + f985180 commit 7109f00
Show file tree
Hide file tree
Showing 7 changed files with 509 additions and 73 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(eosio_contracts)

set(VERSION_MAJOR 1)
set(VERSION_MINOR 8)
set(VERSION_PATCH 2)
set(VERSION_PATCH 3)
#set(VERSION_SUFFIX develop)

if (VERSION_SUFFIX)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# eosio.contracts

## Version : 1.8.2
## Version : 1.8.3

The design of the EOSIO blockchain calls for a number of smart contracts that are run at a privileged permission level in order to support functions such as block producer registration and voting, token staking for CPU and network bandwidth, RAM purchasing, multi-sig, etc. These smart contracts are referred to as the bios, system, msig, wrap (formerly known as sudo) and token contracts.

Expand Down
77 changes: 61 additions & 16 deletions contracts/eosio.system/include/eosio.system/eosio.system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ namespace eosiosystem {

static constexpr uint32_t seconds_per_year = 52 * 7 * 24 * 3600;
static constexpr uint32_t seconds_per_day = 24 * 3600;
static constexpr uint32_t seconds_per_hour = 3600;
static constexpr int64_t useconds_per_year = int64_t(seconds_per_year) * 1000'000ll;
static constexpr int64_t useconds_per_day = int64_t(seconds_per_day) * 1000'000ll;
static constexpr int64_t useconds_per_hour = int64_t(seconds_per_hour) * 1000'000ll;
static constexpr uint32_t blocks_per_day = 2 * seconds_per_day; // half seconds per day

static constexpr int64_t min_activated_stake = 150'000'000'0000;
Expand Down Expand Up @@ -333,6 +335,45 @@ namespace eosiosystem {

typedef eosio::multi_index< "rexpool"_n, rex_pool > rex_pool_table;

// `rex_return_pool` structure underlying the rex return pool table. A rex return pool table entry is defined by:
// - `version` defaulted to zero,
// - `last_dist_time` the last time proceeds from renting, ram fees, and name bids were added to the rex pool,
// - `pending_bucket_time` timestamp of the pending 12-hour return bucket,
// - `oldest_bucket_time` cached timestamp of the oldest 12-hour return bucket,
// - `pending_bucket_proceeds` proceeds in the pending 12-hour return bucket,
// - `current_rate_of_increase` the current rate per dist_interval at which proceeds are added to the rex pool,
// - `proceeds` the maximum amount of proceeds that can be added to the rex pool at any given time
struct [[eosio::table,eosio::contract("eosio.system")]] rex_return_pool {
uint8_t version = 0;
time_point_sec last_dist_time;
time_point_sec pending_bucket_time = time_point_sec::maximum();
time_point_sec oldest_bucket_time = time_point_sec::min();
int64_t pending_bucket_proceeds = 0;
int64_t current_rate_of_increase = 0;
int64_t proceeds = 0;

static constexpr uint32_t total_intervals = 30 * 144; // 30 days
static constexpr uint32_t dist_interval = 10 * 60; // 10 minutes
static constexpr uint8_t hours_per_bucket = 12;
static_assert( total_intervals * dist_interval == 30 * seconds_per_day );

uint64_t primary_key()const { return 0; }
};

typedef eosio::multi_index< "rexretpool"_n, rex_return_pool > rex_return_pool_table;

// `rex_return_buckets` structure underlying the rex return buckets table. A rex return buckets table is defined by:
// - `version` defaulted to zero,
// - `return_buckets` buckets of proceeds accumulated in 12-hour intervals
struct [[eosio::table,eosio::contract("eosio.system")]] rex_return_buckets {
uint8_t version = 0;
std::map<time_point_sec, int64_t> return_buckets;

uint64_t primary_key()const { return 0; }
};

typedef eosio::multi_index< "retbuckets"_n, rex_return_buckets > rex_return_buckets_table;

// `rex_fund` structure underlying the rex fund table. A rex fund table entry is defined by:
// - `version` defaulted to zero,
// - `owner` the owner of the rex fund,
Expand Down Expand Up @@ -430,22 +471,24 @@ namespace eosiosystem {
class [[eosio::contract("eosio.system")]] system_contract : public native {

private:
voters_table _voters;
producers_table _producers;
producers_table2 _producers2;
global_state_singleton _global;
global_state2_singleton _global2;
global_state3_singleton _global3;
global_state4_singleton _global4;
eosio_global_state _gstate;
eosio_global_state2 _gstate2;
eosio_global_state3 _gstate3;
eosio_global_state4 _gstate4;
rammarket _rammarket;
rex_pool_table _rexpool;
rex_fund_table _rexfunds;
rex_balance_table _rexbalance;
rex_order_table _rexorders;
voters_table _voters;
producers_table _producers;
producers_table2 _producers2;
global_state_singleton _global;
global_state2_singleton _global2;
global_state3_singleton _global3;
global_state4_singleton _global4;
eosio_global_state _gstate;
eosio_global_state2 _gstate2;
eosio_global_state3 _gstate3;
eosio_global_state4 _gstate4;
rammarket _rammarket;
rex_pool_table _rexpool;
rex_return_pool_table _rexretpool;
rex_return_buckets_table _rexretbuckets;
rex_fund_table _rexfunds;
rex_balance_table _rexbalance;
rex_order_table _rexorders;

public:
static constexpr eosio::name active_permission{"active"_n};
Expand Down Expand Up @@ -1121,6 +1164,7 @@ namespace eosiosystem {

// defined in rex.cpp
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;
Expand All @@ -1142,6 +1186,7 @@ namespace eosiosystem {
static time_point_sec get_rex_maturity();
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 consolidate_rex_balance( const rex_balance_table::const_iterator& bitr,
const asset& rex_in_sell_order );
Expand Down
3 changes: 2 additions & 1 deletion contracts/eosio.system/src/eosio.system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ namespace eosiosystem {
_global4(get_self(), get_self().value),
_rammarket(get_self(), get_self().value),
_rexpool(get_self(), get_self().value),
_rexretpool(get_self(), get_self().value),
_rexretbuckets(get_self(), get_self().value),
_rexfunds(get_self(), get_self().value),
_rexbalance(get_self(), get_self().value),
_rexorders(get_self(), get_self().value)
{
//print( "construct system\n" );
_gstate = _global.exists() ? _global.get() : get_default_parameters();
_gstate2 = _global2.exists() ? _global2.get() : eosio_global_state2{};
_gstate3 = _global3.exists() ? _global3.get() : eosio_global_state3{};
Expand Down
152 changes: 144 additions & 8 deletions contracts/eosio.system/src/rex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace eosiosystem {

using eosio::current_time_point;
using eosio::token;
using eosio::seconds;

void system_contract::deposit( const name& owner, const asset& amount )
{
Expand Down Expand Up @@ -452,15 +453,13 @@ namespace eosiosystem {
*/
void system_contract::add_loan_to_rex_pool( const asset& payment, int64_t rented_tokens, bool new_loan )
{
add_to_rex_return_pool( payment );
_rexpool.modify( _rexpool.begin(), same_payer, [&]( auto& rt ) {
// add payment to total_rent
rt.total_rent.amount += payment.amount;
// move rented_tokens from total_unlent to total_lent
rt.total_unlent.amount -= rented_tokens;
rt.total_lent.amount += rented_tokens;
// add payment to total_unlent
rt.total_unlent.amount += payment.amount;
rt.total_lendable.amount = rt.total_unlent.amount + rt.total_lent.amount;
// increment loan_num if a new loan is being created
if ( new_loan ) {
rt.loan_num++;
Expand Down Expand Up @@ -513,6 +512,8 @@ namespace eosiosystem {
{
check( rex_system_initialized(), "rex system not initialized yet" );

update_rex_pool();

const auto& pool = _rexpool.begin();

auto process_expired_loan = [&]( auto& idx, const auto& itr ) -> std::pair<bool, int64_t> {
Expand Down Expand Up @@ -616,6 +617,108 @@ namespace eosiosystem {

}

/**
* @brief Adds returns from the REX return pool to the REX pool
*/
void system_contract::update_rex_pool()
{
auto get_elapsed_intervals = [&]( const time_point_sec& t1, const time_point_sec& t0 ) -> uint32_t {
return ( t1.sec_since_epoch() - t0.sec_since_epoch() ) / rex_return_pool::dist_interval;
};

const time_point_sec ct = current_time_point();
const uint32_t cts = ct.sec_since_epoch();
const time_point_sec effective_time{cts - cts % rex_return_pool::dist_interval};

const auto ret_pool_elem = _rexretpool.begin();
const auto ret_buckets_elem = _rexretbuckets.begin();

if ( ret_pool_elem == _rexretpool.end() || effective_time <= ret_pool_elem->last_dist_time ) {
return;
}

const int64_t current_rate = ret_pool_elem->current_rate_of_increase;
const uint32_t elapsed_intervals = get_elapsed_intervals( effective_time, ret_pool_elem->last_dist_time );
int64_t change_estimate = current_rate * elapsed_intervals;

{
const bool new_return_bucket = ret_pool_elem->pending_bucket_time <= effective_time;
int64_t new_bucket_rate = 0;
time_point_sec new_bucket_time = time_point_sec::min();
_rexretpool.modify( ret_pool_elem, same_payer, [&]( auto& rp ) {
if ( new_return_bucket ) {
int64_t remainder = rp.pending_bucket_proceeds % rex_return_pool::total_intervals;
new_bucket_rate = ( rp.pending_bucket_proceeds - remainder ) / rex_return_pool::total_intervals;
new_bucket_time = rp.pending_bucket_time;
rp.current_rate_of_increase += new_bucket_rate;
change_estimate += remainder + new_bucket_rate * get_elapsed_intervals( effective_time, rp.pending_bucket_time );
rp.pending_bucket_proceeds = 0;
rp.pending_bucket_time = time_point_sec::maximum();
if ( new_bucket_time < rp.oldest_bucket_time ) {
rp.oldest_bucket_time = new_bucket_time;
}
}
rp.proceeds -= change_estimate;
rp.last_dist_time = effective_time;
});

if ( new_return_bucket ) {
_rexretbuckets.modify( ret_buckets_elem, same_payer, [&]( auto& rb ) {
rb.return_buckets[new_bucket_time] = new_bucket_rate;
});
}
}

const time_point_sec time_threshold = effective_time - seconds(rex_return_pool::total_intervals * rex_return_pool::dist_interval);
if ( ret_pool_elem->oldest_bucket_time <= time_threshold ) {
int64_t expired_rate = 0;
int64_t surplus = 0;
_rexretbuckets.modify( ret_buckets_elem, same_payer, [&]( auto& rb ) {
auto& return_buckets = rb.return_buckets;
auto iter = return_buckets.begin();
while ( iter != return_buckets.end() && iter->first <= time_threshold ) {
auto next = iter;
++next;
const uint32_t overtime = get_elapsed_intervals( effective_time,
iter->first + seconds(rex_return_pool::total_intervals * rex_return_pool::dist_interval) );
surplus += iter->second * overtime;
expired_rate += iter->second;
return_buckets.erase(iter);
iter = next;
}
});

_rexretpool.modify( ret_pool_elem, same_payer, [&]( auto& rp ) {
if ( !ret_buckets_elem->return_buckets.empty() ) {
rp.oldest_bucket_time = ret_buckets_elem->return_buckets.begin()->first;
} else {
rp.oldest_bucket_time = time_point_sec::min();
}
if ( expired_rate > 0) {
rp.current_rate_of_increase -= expired_rate;
}
if ( surplus > 0 ) {
change_estimate -= surplus;
rp.proceeds += surplus;
}
});
}

if ( change_estimate > 0 && ret_pool_elem->proceeds < 0 ) {
_rexretpool.modify( ret_pool_elem, same_payer, [&]( auto& rp ) {
change_estimate += rp.proceeds;
rp.proceeds = 0;
});
}

if ( change_estimate > 0 ) {
_rexpool.modify( _rexpool.begin(), same_payer, [&]( auto& pool ) {
pool.total_unlent.amount += change_estimate;
pool.total_lendable = pool.total_unlent + pool.total_lent;
});
}
}

template <typename T>
int64_t system_contract::rent_rex( T& table, const name& from, const name& receiver, const asset& payment, const asset& fund )
{
Expand Down Expand Up @@ -678,7 +781,7 @@ namespace eosiosystem {
asset stake_change( 0, core_symbol() );
bool success = false;

const int64_t unlent_lower_bound = ( uint128_t(2) * rexitr->total_lent.amount ) / 10;
const int64_t unlent_lower_bound = rexitr->total_lent.amount / 10;
const int64_t available_unlent = rexitr->total_unlent.amount - unlent_lower_bound; // available_unlent <= 0 is possible
if ( proceeds.amount <= available_unlent ) {
const int64_t init_vote_stake_amount = bitr->vote_stake.amount;
Expand Down Expand Up @@ -818,10 +921,7 @@ namespace eosiosystem {
{
#if CHANNEL_RAM_AND_NAMEBID_FEES_TO_REX
if ( rex_available() ) {
_rexpool.modify( _rexpool.begin(), same_payer, [&]( auto& rp ) {
rp.total_unlent.amount += amount.amount;
rp.total_lendable.amount += amount.amount;
});
add_to_rex_return_pool( amount );
// inline transfer to rex_account
token::transfer_action transfer_act{ token_account, { from, active_permission } };
transfer_act.send( from, rex_account, amount,
Expand Down Expand Up @@ -961,6 +1061,42 @@ namespace eosiosystem {
return rex_received;
}

/**
* @brief Adds an amount of core tokens to the REX return pool
*
* @param fee - amount to be added
*/
void system_contract::add_to_rex_return_pool( const asset& fee )
{
update_rex_pool();
if ( fee.amount <= 0 ) {
return;
}

const time_point_sec ct = current_time_point();
const uint32_t cts = ct.sec_since_epoch();
const uint32_t bucket_interval = rex_return_pool::hours_per_bucket * seconds_per_hour;
const time_point_sec effective_time{cts - cts % bucket_interval + bucket_interval};
const auto return_pool_elem = _rexretpool.begin();
if ( return_pool_elem == _rexretpool.end() ) {
_rexretpool.emplace( get_self(), [&]( auto& rp ) {
rp.last_dist_time = effective_time;
rp.pending_bucket_proceeds = fee.amount;
rp.pending_bucket_time = effective_time;
rp.proceeds = fee.amount;
});
_rexretbuckets.emplace( get_self(), [&]( auto& rb ) { } );
} else {
_rexretpool.modify( return_pool_elem, same_payer, [&]( auto& rp ) {
rp.pending_bucket_proceeds += fee.amount;
rp.proceeds += fee.amount;
if ( rp.pending_bucket_time == time_point_sec::maximum() ) {
rp.pending_bucket_time = effective_time;
}
});
}
}

/**
* @brief Updates owner REX balance upon buying REX tokens
*
Expand Down
Loading

0 comments on commit 7109f00

Please sign in to comment.