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 #397 from EOSIO/resource31
Browse files Browse the repository at this point in the history
rentbw
  • Loading branch information
arhag authored Dec 20, 2019
2 parents aa22170 + 6c8451b commit affe696
Show file tree
Hide file tree
Showing 6 changed files with 1,427 additions and 6 deletions.
1 change: 1 addition & 0 deletions contracts/eosio.system/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_contract(eosio.system eosio.system
${CMAKE_CURRENT_SOURCE_DIR}/src/exchange_state.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/native.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/producer_pay.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rentbw.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/voting.cpp
)
Expand Down
169 changes: 165 additions & 4 deletions contracts/eosio.system/include/eosio.system/eosio.system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace eosiosystem {
using eosio::time_point_sec;
using eosio::unsigned_int;

inline constexpr int64_t rentbw_frac = 1'000'000'000'000'000ll; // 1.0 = 10^15

template<typename E, typename F>
static inline auto has_field( F flags, E field )
-> std::enable_if_t< std::is_integral_v<F> && std::is_unsigned_v<F> &&
Expand Down Expand Up @@ -85,6 +87,7 @@ namespace eosiosystem {
* - Users can bid on premium names.
* - A resource exchange system (REX) allows token holders to lend their tokens,
* and users to rent CPU and Network resources in return for a market-determined fee.
* - A resource market separate from REX: `rentbw`
*/

// A name bid, which consists of:
Expand Down Expand Up @@ -339,8 +342,8 @@ namespace eosiosystem {
// - `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,
// - `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 {
Expand All @@ -364,7 +367,7 @@ namespace eosiosystem {

// `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
// - `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;
Expand Down Expand Up @@ -465,6 +468,123 @@ namespace eosiosystem {
asset stake_change;
};

struct rentbw_config_resource {
std::optional<int64_t> current_weight_ratio; // Immediately set weight_ratio to this amount. 1x = 10^15. 0.01x = 10^13.
// Do not specify to preserve the existing setting or use the default;
// this avoids sudden price jumps. For new chains which don't need
// to gradually phase out staking and REX, 0.01x (10^13) is a good
// value for both current_weight_ratio and target_weight_ratio.
std::optional<int64_t> target_weight_ratio; // Linearly shrink weight_ratio to this amount. 1x = 10^15. 0.01x = 10^13.
// Do not specify to preserve the existing setting or use the default.
std::optional<int64_t> assumed_stake_weight; // Assumed stake weight for ratio calculations. Use the sum of total
// staked and total rented by REX at the time the rentbw market
// is first activated. Do not specify to preserve the existing
// setting (no default exists); this avoids sudden price jumps.
// For new chains which don't need to phase out staking and REX,
// 10^12 is probably a good value.
std::optional<time_point_sec> target_timestamp; // Stop automatic weight_ratio shrinkage at this time. Once this
// time hits, weight_ratio will be target_weight_ratio. Ignored
// if current_weight_ratio == target_weight_ratio. Do not specify
// this to preserve the existing setting (no default exists).
std::optional<double> exponent; // Exponent of resource price curve. Must be >= 1. Do not specify
// to preserve the existing setting or use the default.
std::optional<uint32_t> decay_secs; // Number of seconds for the gap between adjusted resource
// utilization and instantaneous resource utilization to shrink
// by 63%. Do not specify to preserve the existing setting or
// use the default.
std::optional<asset> min_price; // Fee needed to rent the entire resource market weight at the
// minimum price. For example, this could be set to 0.005% of
// total token supply. Do not specify to preserve the existing
// setting or use the default.
std::optional<asset> max_price; // Fee needed to rent the entire resource market weight at the
// maximum price. For example, this could be set to 10% of total
// token supply. Do not specify to preserve the existing
// setting (no default exists).

EOSLIB_SERIALIZE( rentbw_config_resource, (current_weight_ratio)(target_weight_ratio)(assumed_stake_weight)
(target_timestamp)(exponent)(decay_secs)(min_price)(max_price) )
};

struct rentbw_config {
rentbw_config_resource net; // NET market configuration
rentbw_config_resource cpu; // CPU market configuration
std::optional<uint32_t> rent_days; // `rentbw` `days` argument must match this. Do not specify to preserve the
// existing setting or use the default.
std::optional<asset> min_rent_fee; // Rental fees below this amount are rejected. Do not specify to preserve the
// existing setting (no default exists).

EOSLIB_SERIALIZE( rentbw_config, (net)(cpu)(rent_days)(min_rent_fee) )
};

struct rentbw_state_resource {
static constexpr double default_exponent = 2.0; // Exponent of 2.0 means that the price to rent a
// tiny amount of resources increases linearly
// with utilization.
static constexpr uint32_t default_decay_secs = 1 * seconds_per_day; // 1 day; if 100% of bandwidth resources are in a
// single loan, then, assuming no further renting,
// 1 day after it expires the adjusted utilization
// will be at approximately 37% and after 3 days
// the adjusted utilization will be less than 5%.

uint8_t version = 0;
int64_t weight = 0; // resource market weight. calculated; varies over time.
// 1 represents the same amount of resources as 1
// satoshi of SYS staked.
int64_t weight_ratio = 0; // resource market weight ratio:
// assumed_stake_weight / (assumed_stake_weight + weight).
// calculated; varies over time. 1x = 10^15. 0.01x = 10^13.
int64_t assumed_stake_weight = 0; // Assumed stake weight for ratio calculations.
int64_t initial_weight_ratio = rentbw_frac; // Initial weight_ratio used for linear shrinkage.
int64_t target_weight_ratio = rentbw_frac / 100; // Linearly shrink the weight_ratio to this amount.
time_point_sec initial_timestamp = {}; // When weight_ratio shrinkage started
time_point_sec target_timestamp = {}; // Stop automatic weight_ratio shrinkage at this time. Once this
// time hits, weight_ratio will be target_weight_ratio.
double exponent = default_exponent; // Exponent of resource price curve.
uint32_t decay_secs = default_decay_secs; // Number of seconds for the gap between adjusted resource
// utilization and instantaneous utilization to shrink by 63%.
asset min_price = {}; // Fee needed to rent the entire resource market weight at
// the minimum price (defaults to 0).
asset max_price = {}; // Fee needed to rent the entire resource market weight at
// the maximum price.
int64_t utilization = 0; // Instantaneous resource utilization. This is the current
// amount sold. utilization <= weight.
int64_t adjusted_utilization = 0; // Adjusted resource utilization. This is >= utilization and
// <= weight. It grows instantly but decays exponentially.
time_point_sec utilization_timestamp = {}; // When adjusted_utilization was last updated
};

struct [[eosio::table("rent.state"),eosio::contract("eosio.system")]] rentbw_state {
static constexpr uint32_t default_rent_days = 30; // 30 day resource rentals

uint8_t version = 0;
rentbw_state_resource net = {}; // NET market state
rentbw_state_resource cpu = {}; // CPU market state
uint32_t rent_days = default_rent_days; // `rentbw` `days` argument must match this.
asset min_rent_fee = {}; // Rental fees below this amount are rejected

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

typedef eosio::singleton<"rent.state"_n, rentbw_state> rentbw_state_singleton;

struct [[eosio::table("rentbw.order"),eosio::contract("eosio.system")]] rentbw_order {
uint8_t version = 0;
uint64_t id;
name owner;
int64_t net_weight;
int64_t cpu_weight;
time_point_sec expires;

uint64_t primary_key()const { return id; }
uint64_t by_owner()const { return owner.value; }
uint64_t by_expires()const { return expires.utc_seconds; }
};

typedef eosio::multi_index< "rentbw.order"_n, rentbw_order,
indexed_by<"byowner"_n, const_mem_fun<rentbw_order, uint64_t, &rentbw_order::by_owner>>,
indexed_by<"byexpires"_n, const_mem_fun<rentbw_order, uint64_t, &rentbw_order::by_expires>>
> rentbw_order_table;

/**
* The EOSIO system contract. The EOSIO system contract governs ram market, voters, producers, global state.
*/
Expand Down Expand Up @@ -501,6 +621,7 @@ namespace eosiosystem {
static constexpr eosio::name names_account{"eosio.names"_n};
static constexpr eosio::name saving_account{"eosio.saving"_n};
static constexpr eosio::name rex_account{"eosio.rex"_n};
static constexpr eosio::name reserv_account{"eosio.reserv"_n};
static constexpr eosio::name null_account{"eosio.null"_n};
static constexpr symbol ramcore_symbol = symbol(symbol_code("RAMCORE"), 4);
static constexpr symbol ram_symbol = symbol(symbol_code("RAM"), 0);
Expand Down Expand Up @@ -1101,6 +1222,36 @@ namespace eosiosystem {
[[eosio::action]]
void setinflation( int64_t annual_rate, int64_t inflation_pay_factor, int64_t votepay_factor );

/**
* Configure the `rentbw` market. The market becomes available the first time this
* action is invoked.
*/
[[eosio::action]]
void configrentbw( rentbw_config& args );

/**
* Process rentbw queue and update state. Action does not execute anything related to a specific user.
*
* @param user - any account can execute this action
* @param max - number of queue items to process
*/
[[eosio::action]]
void rentbwexec( const name& user, uint16_t max );

/**
* Rent NET and CPU
*
* @param payer - the resource buyer
* @param receiver - the resource receiver
* @param days - number of days of resource availability. Must match market configuration.
* @param net_frac - fraction of net (100% = 10^15) managed by this market
* @param cpu_frac - fraction of cpu (100% = 10^15) managed by this market
* @param max_payment - the maximum amount `payer` is willing to pay. Tokens are withdrawn from
* `payer`'s token balance.
*/
[[eosio::action]]
void rentbw( const name& payer, const name& receiver, uint32_t days, int64_t net_frac, int64_t cpu_frac, const asset& max_payment );

using init_action = eosio::action_wrapper<"init"_n, &system_contract::init>;
using setacctram_action = eosio::action_wrapper<"setacctram"_n, &system_contract::setacctram>;
using setacctnet_action = eosio::action_wrapper<"setacctnet"_n, &system_contract::setacctnet>;
Expand Down Expand Up @@ -1146,6 +1297,9 @@ namespace eosiosystem {
using setalimits_action = eosio::action_wrapper<"setalimits"_n, &system_contract::setalimits>;
using setparams_action = eosio::action_wrapper<"setparams"_n, &system_contract::setparams>;
using setinflation_action = eosio::action_wrapper<"setinflation"_n, &system_contract::setinflation>;
using configrentbw_action = eosio::action_wrapper<"configrentbw"_n, &system_contract::configrentbw>;
using rentbwexec_action = eosio::action_wrapper<"rentbwexec"_n, &system_contract::rentbwexec>;
using rentbw_action = eosio::action_wrapper<"rentbw"_n, &system_contract::rentbw>;

private:
// Implementation details:
Expand All @@ -1170,7 +1324,7 @@ namespace eosiosystem {
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 );
void channel_to_rex( const name& from, const asset& amount );
void channel_to_rex( const name& from, const asset& amount, bool required = false );
void channel_namebid_to_rex( const int64_t highest_bid );
template <typename T>
int64_t rent_rex( T& table, const name& from, const name& receiver, const asset& loan_payment, const asset& loan_fund );
Expand Down Expand Up @@ -1245,6 +1399,13 @@ namespace eosiosystem {
};

registration<&system_contract::update_rex_stake> vote_stake_updater{ this };

// defined in rentbw.cpp
void adjust_resources(name payer, name account, symbol core_symbol, int64_t net_delta, int64_t cpu_delta, bool must_not_be_managed = false);
void process_rentbw_queue(
time_point_sec now, symbol core_symbol, rentbw_state& state,
rentbw_order_table& orders, uint32_t max_items, int64_t& net_delta_available,
int64_t& cpu_delta_available);
};

}
Loading

0 comments on commit affe696

Please sign in to comment.