diff --git a/.gitignore b/.gitignore index 899a087..6d1be74 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ !/external/**/*.abi !/external/**/*.wasm node_modules +build .DS_Store eosc-vault.json package-lock.json diff --git a/eosio.bpay.contracts.md b/eosio.bpay.contracts.md index 1b759a1..0d93411 100644 --- a/eosio.bpay.contracts.md +++ b/eosio.bpay.contracts.md @@ -2,9 +2,9 @@ --- spec_version: "0.2.0" -title: claimrewards -summary: 'Claim Rewards' -icon: https://gateway.pinata.cloud/ipfs/QmZ4HSZDuSrZ4BHawtZRhVfwyYJ4DepNJqVDzxY59KveiM#3830f1ce8cb07f7757dbcf383b1ec1b11914ac34a1f9d8b065f07600fa9dac19 +title: Claim Rewards +summary: '{{nowrap owner}} claims block production rewards' +icon: https://gateway.pinata.cloud/ipfs/QmUkZgGySiqZnA4bKSwY39KzfnsearL5icErN6b2jdHvoe#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e --- -Claim rewards {{ owner }} has earned as a block producer. +{{owner}} claims block production rewards accumulated through network fees. diff --git a/eosio.bpay.cpp b/eosio.bpay.cpp index cdae137..d6a82fb 100644 --- a/eosio.bpay.cpp +++ b/eosio.bpay.cpp @@ -1,66 +1,60 @@ -#include "eosio.bpay.hpp" +#include "./eosio.bpay.hpp" namespace eosio { -[[eosio::action]] void bpay::claimrewards( const name owner ) { require_auth( owner ); rewards_table _rewards( get_self(), get_self().value ); - const auto& row = _rewards.get( owner.value, "not eligible to claim producer block pay" ); - check( row.quantity.amount > 0, "no rewards to claim"); + const auto& row = _rewards.get( owner.value, "no rewards to claim" ); - // transfer rewards to owner eosio::token::transfer_action transfer( "eosio.token"_n, { get_self(), "active"_n }); transfer.send( get_self(), owner, row.quantity, "producer block pay" ); - _rewards.modify(row, get_self(), [&](auto& row) { - row.quantity.amount = 0; - }); + _rewards.erase(row); } -[[eosio::on_notify("*::transfer")]] -void bpay::on_transfer( const name from, const name to, const asset quantity, const string memo ) -{ +void bpay::on_transfer( const name from, const name to, const asset quantity, const string memo ) { if (from == get_self() || to != get_self()) { return; } + // ignore eosio system incoming transfers (caused by bpay income transfers eosio => eosio.bpay => producer) if ( from == "eosio"_n) return; - check( get_first_receiver() == "eosio.token"_n, "only eosio.token allowed") ; - check( quantity.symbol == eosio::symbol("EOS", 4), "only EOS token allowed" ); + symbol system_symbol = eosiosystem::system_contract::get_core_symbol(); + + check( quantity.symbol == system_symbol, "only core token allowed" ); rewards_table _rewards( get_self(), get_self().value ); eosiosystem::system_contract::producers_table _producers( "eosio"_n, "eosio"_n.value ); - // calculate rewards equal share for top 21 producers - asset reward = quantity / 21; + eosiosystem::system_contract::global_state_singleton _global("eosio"_n, "eosio"_n.value); + check( _global.exists(), "global state does not exist"); + uint16_t producer_count = _global.get().last_producer_schedule_size; + + asset reward = quantity / producer_count; // get producer with the most votes // using `by_votes` secondary index auto idx = _producers.get_index<"prototalvote"_n>(); auto prod = idx.begin(); - // get top 21 producers by vote + // get top n producers by vote, excluding inactive std::vector top_producers; while (true) { - if ( prod == idx.end() ) { - break; - } - if ( prod->is_active == false ) { - continue; - } + if (prod == idx.end()) break; + if (prod->is_active == false) continue; + top_producers.push_back(prod->owner); - print("rank=", top_producers.size(), " producer=", prod->owner, " reward=", reward.to_string(), "\n"); - if ( top_producers.size() == 21 ) { - break; - } + + if (top_producers.size() == producer_count) break; + prod++; } - // update rewards table + // distribute rewards to top producers for (auto producer : top_producers) { auto row = _rewards.find( producer.value ); if (row == _rewards.end()) { diff --git a/eosio.bpay.hpp b/eosio.bpay.hpp index 5cf6290..042ebd3 100644 --- a/eosio.bpay.hpp +++ b/eosio.bpay.hpp @@ -47,7 +47,7 @@ namespace eosio { [[eosio::action]] void claimrewards( const name owner); - [[eosio::on_notify("*::transfer")]] + [[eosio::on_notify("eosio.token::transfer")]] void on_transfer( const name from, const name to, const asset quantity, const string memo ); private: diff --git a/eosio.bpay.permission.yml b/eosio.bpay.permission.yml index da7d1a6..8c1292e 100644 --- a/eosio.bpay.permission.yml +++ b/eosio.bpay.permission.yml @@ -7,17 +7,13 @@ owner: weight: 1 active: - threshold: 2 + threshold: 1 accounts: - permission: - actor: enf + actor: eosio permission: active weight: 1 - - permission: - actor: eosio.prods - permission: prod.minor - weight: 1 - permission: actor: eosio.bpay permission: eosio.code - weight: 2 \ No newline at end of file + weight: 1 \ No newline at end of file diff --git a/icons/admin.png b/icons/admin.png new file mode 100644 index 0000000..ae95364 Binary files /dev/null and b/icons/admin.png differ diff --git a/icons/admin.svg b/icons/admin.svg new file mode 100644 index 0000000..fbc0571 --- /dev/null +++ b/icons/admin.svg @@ -0,0 +1 @@ +Admin \ No newline at end of file diff --git a/icons/multisig.png b/icons/multisig.png new file mode 100644 index 0000000..00fa756 Binary files /dev/null and b/icons/multisig.png differ diff --git a/icons/multisig.svg b/icons/multisig.svg new file mode 100644 index 0000000..d9167fb --- /dev/null +++ b/icons/multisig.svg @@ -0,0 +1 @@ +Multi Sig \ No newline at end of file diff --git a/include/eosio.system/eosio.system.hpp b/include/eosio.system/eosio.system.hpp index ba9d2c4..121d4f5 100644 --- a/include/eosio.system/eosio.system.hpp +++ b/include/eosio.system/eosio.system.hpp @@ -1,7 +1,10 @@ +#include #include #include +#include #include #include +#include #include @@ -18,6 +21,12 @@ class [[eosio::contract("eosio")]] system_contract : public contract return eosio::block_signing_authority_v0{ .threshold = 1, .keys = {{producer_key, 1}} }; } + // Returns the core symbol by system account name + // @param system_account - the system account to get the core symbol for. + static eosio::symbol get_core_symbol( name system_account = "eosio"_n ) { + return symbol(symbol_code("EOS"), 4); + } + // Defines `producer_info` structure to be stored in `producer_info` table, added after version 1.0 struct [[eosio::table, eosio::contract("eosio.system")]] producer_info { name owner; @@ -90,5 +99,33 @@ class [[eosio::contract("eosio")]] system_contract : public contract typedef eosio::multi_index< "producers"_n, producer_info, indexed_by<"prototalvote"_n, const_mem_fun> > producers_table; + + // Defines new global state parameters. + struct [[eosio::table("global"), eosio::contract("eosio.system")]] eosio_global_state : eosio::blockchain_parameters { + uint64_t free_ram()const { return max_ram_size - total_ram_bytes_reserved; } + + uint64_t max_ram_size = 64ll*1024 * 1024 * 1024; + uint64_t total_ram_bytes_reserved = 0; + int64_t total_ram_stake = 0; + + block_timestamp last_producer_schedule_update; + time_point last_pervote_bucket_fill; + int64_t pervote_bucket = 0; + int64_t perblock_bucket = 0; + uint32_t total_unpaid_blocks = 0; /// all blocks which have been produced but not paid + int64_t total_activated_stake = 0; + time_point thresh_activated_stake_time; + uint16_t last_producer_schedule_size = 0; + double total_producer_vote_weight = 0; /// the sum of all producer votes + block_timestamp last_name_close; + + // explicit serialization macro is not necessary, used here only to improve compilation time + EOSLIB_SERIALIZE_DERIVED( eosio_global_state, eosio::blockchain_parameters, + (max_ram_size)(total_ram_bytes_reserved)(total_ram_stake) + (last_producer_schedule_update)(last_pervote_bucket_fill) + (pervote_bucket)(perblock_bucket)(total_unpaid_blocks)(total_activated_stake)(thresh_activated_stake_time) + (last_producer_schedule_size)(total_producer_vote_weight)(last_name_close) ) + }; + typedef eosio::singleton< "global"_n, eosio_global_state > global_state_singleton; }; } \ No newline at end of file