Skip to content

Commit

Permalink
push fees upgrade changes
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisCarriere committed May 2, 2024
1 parent 732fa98 commit 47e44bd
Show file tree
Hide file tree
Showing 18 changed files with 373 additions and 101 deletions.
1 change: 1 addition & 0 deletions contracts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ add_subdirectory(eosio.msig)
add_subdirectory(eosio.system)
add_subdirectory(eosio.token)
add_subdirectory(eosio.wrap)
add_subdirectory(eosio.fees)

add_subdirectory(test_contracts)
11 changes: 11 additions & 0 deletions contracts/eosio.fees/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_contract(eosio.fees eosio.fees ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.fees.cpp)

target_include_directories(eosio.fees PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/../eosio.system/include)

set_target_properties(eosio.fees
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")

target_compile_options( eosio.fees PUBLIC )
35 changes: 35 additions & 0 deletions contracts/eosio.fees/include/eosio.fees/eosio.fees.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <eosio/asset.hpp>
#include <eosio/eosio.hpp>
#include <eosio.system/eosio.system.hpp>

#include <string>

namespace eosiosystem {
class system_contract;
}

namespace eosio {

using std::string;
/**
* The eosio.fees smart contract facilitates the collection of transaction fees from system accounts and their subsequent distribution to the Resource Exchange (REX) pool.
*
* This contract serves as an essential component for inclusion in system-level unit tests.
*
* A comprehensive implementation of the eosio.fees contract can be accessed at EOS Network Foundation GitHub repository.
* https://github.com/eosnetworkfoundation/eosio.fees
*/
class [[eosio::contract("eosio.fees")]] fees : public contract {
public:
using contract::contract;

[[eosio::on_notify("eosio.token::transfer")]]
void on_transfer( const name from, const name to, const asset quantity, const string memo );

[[eosio::action]]
void noop();
};

}
21 changes: 21 additions & 0 deletions contracts/eosio.fees/src/eosio.fees.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <eosio.fees/eosio.fees.hpp>

namespace eosio {

void fees::on_transfer( const name from, const name to, const asset quantity, const string memo )
{
if ( to != get_self() ) {
return;
}
if (eosiosystem::system_contract::rex_available()) {
eosiosystem::system_contract::donatetorex_action donatetorex( "eosio"_n, { get_self(), "active"_n });
donatetorex.send(get_self(), quantity, memo);
}
}

void fees::noop()
{
require_auth( get_self() );
}

} /// namespace eosio
75 changes: 59 additions & 16 deletions contracts/eosio.system/include/eosio.system/eosio.system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ namespace eosiosystem {
asset quantity;
int64_t bytes_sold;
int64_t ram_bytes;
asset fee;
};

struct action_return_buyram {
Expand All @@ -558,6 +559,7 @@ namespace eosiosystem {
asset quantity;
int64_t bytes_purchased;
int64_t ram_bytes;
asset fee;
};

struct action_return_ramtransfer {
Expand Down Expand Up @@ -732,6 +734,8 @@ 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 fees_account{"eosio.fees"_n};
static constexpr eosio::name powerup_account{"eosio.powup"_n};
static constexpr eosio::name reserve_account{"eosio.reserv"_n}; // cspell:disable-line
static constexpr eosio::name null_account{"eosio.null"_n};
static constexpr symbol ramcore_symbol = symbol(symbol_code("RAMCORE"), 4);
Expand All @@ -745,8 +749,21 @@ namespace eosiosystem {
// @param system_account - the system account to get the core symbol for.
static symbol get_core_symbol( name system_account = "eosio"_n ) {
rammarket rm(system_account, system_account.value);
const static auto sym = get_core_symbol( rm );
return sym;
auto itr = rm.find(ramcore_symbol.raw());
check(itr != rm.end(), "system contract must first be initialized");
return itr->quote.balance.symbol;
}

// Returns true/false if the rex system is initialized
static bool rex_system_initialized( name system_account = "eosio"_n ) {
eosiosystem::rex_pool_table _rexpool( system_account, system_account.value );
return _rexpool.begin() != _rexpool.end();
}

// Returns true/false if the rex system is available
static bool rex_available( name system_account = "eosio"_n ) {
eosiosystem::rex_pool_table _rexpool( system_account, system_account.value );
return rex_system_initialized() && _rexpool.begin()->total_rex.amount > 0;
}

// Actions:
Expand Down Expand Up @@ -823,6 +840,16 @@ namespace eosiosystem {
[[eosio::action]]
void activate( const eosio::checksum256& feature_digest );

/**
* Logging for actions resulting in system fees.
*
* @param protocol - name of protocol fees were earned from.
* @param fee - the amount of fees collected by system.
* @param memo - (optional) the memo associated with the action.
*/
[[eosio::action]]
void logsystemfee( const name& protocol, const asset& fee, const std::string& memo );

// functions defined in delegate_bandwidth.cpp

/**
Expand Down Expand Up @@ -1079,6 +1106,17 @@ namespace eosiosystem {
[[eosio::action]]
void closerex( const name& owner );

/**
* Donatetorex action, donates funds to REX, increases REX pool return buckets
* Executes inline transfer from payer to system contract of tokens will be executed.
*
* @param payer - the payer of donated funds.
* @param quantity - the quantity of tokens to donated to REX with.
* @param memo - the memo string to accompany the transaction.
*/
[[eosio::action]]
void donatetorex( const name& payer, const asset& quantity, const std::string& memo );

/**
* Undelegate bandwidth action, decreases the total tokens delegated by `from` to `receiver` and/or
* frees the memory associated with the delegation if there is nothing
Expand Down Expand Up @@ -1152,9 +1190,10 @@ namespace eosiosystem {
* @param quantity - the quantity of tokens to buy ram with.
* @param bytes - the quantity of ram to buy specified in bytes.
* @param ram_bytes - the ram bytes held by receiver after the action.
* @param fee - the fee to be paid for the ram sold.
*/
[[eosio::action]]
void logbuyram( const name& payer, const name& receiver, const asset& quantity, int64_t bytes, int64_t ram_bytes );
void logbuyram( const name& payer, const name& receiver, const asset& quantity, int64_t bytes, int64_t ram_bytes, const asset& fee );

/**
* Sell ram action, reduces quota by bytes and then performs an inline transfer of tokens
Expand All @@ -1173,9 +1212,10 @@ namespace eosiosystem {
* @param quantity - the quantity of tokens to sell ram with.
* @param bytes - the quantity of ram to sell specified in bytes.
* @param ram_bytes - the ram bytes held by account after the action.
* @param fee - the fee to be paid for the ram sold.
*/
[[eosio::action]]
void logsellram( const name& account, const asset& quantity, int64_t bytes, int64_t ram_bytes );
void logsellram( const name& account, const asset& quantity, int64_t bytes, int64_t ram_bytes, const asset& fee );

/**
* Transfer ram action, reduces sender's quota by bytes and increase receiver's quota by bytes.
Expand All @@ -1198,6 +1238,17 @@ namespace eosiosystem {
[[eosio::action]]
action_return_ramtransfer ramburn( const name& owner, int64_t bytes, const std::string& memo );

/**
* Buy RAM and immediately burn RAM.
* An inline transfer from payer to system contract of tokens will be executed.
*
* @param payer - the payer of buy RAM & burn.
* @param quantity - the quantity of tokens to buy RAM & burn with.
* @param memo - the memo string to accompany the transaction.
*/
[[eosio::action]]
action_return_buyram buyramburn( const name& payer, const asset& quantity, const std::string& memo );

/**
* Logging for ram changes
*
Expand Down Expand Up @@ -1482,6 +1533,7 @@ namespace eosiosystem {
using setacctnet_action = eosio::action_wrapper<"setacctnet"_n, &system_contract::setacctnet>;
using setacctcpu_action = eosio::action_wrapper<"setacctcpu"_n, &system_contract::setacctcpu>;
using activate_action = eosio::action_wrapper<"activate"_n, &system_contract::activate>;
using logsystemfee_action = eosio::action_wrapper<"logsystemfee"_n, &system_contract::logsystemfee>;
using delegatebw_action = eosio::action_wrapper<"delegatebw"_n, &system_contract::delegatebw>;
using deposit_action = eosio::action_wrapper<"deposit"_n, &system_contract::deposit>;
using withdraw_action = eosio::action_wrapper<"withdraw"_n, &system_contract::withdraw>;
Expand All @@ -1502,6 +1554,7 @@ namespace eosiosystem {
using mvfrsavings_action = eosio::action_wrapper<"mvfrsavings"_n, &system_contract::mvfrsavings>;
using consolidate_action = eosio::action_wrapper<"consolidate"_n, &system_contract::consolidate>;
using closerex_action = eosio::action_wrapper<"closerex"_n, &system_contract::closerex>;
using donatetorex_action = eosio::action_wrapper<"donatetorex"_n, &system_contract::donatetorex>;
using undelegatebw_action = eosio::action_wrapper<"undelegatebw"_n, &system_contract::undelegatebw>;
using buyram_action = eosio::action_wrapper<"buyram"_n, &system_contract::buyram>;
using buyrambytes_action = eosio::action_wrapper<"buyrambytes"_n, &system_contract::buyrambytes>;
Expand All @@ -1510,6 +1563,7 @@ namespace eosiosystem {
using logsellram_action = eosio::action_wrapper<"logsellram"_n, &system_contract::logsellram>;
using ramtransfer_action = eosio::action_wrapper<"ramtransfer"_n, &system_contract::ramtransfer>;
using ramburn_action = eosio::action_wrapper<"ramburn"_n, &system_contract::ramburn>;
using buyramburn_action = eosio::action_wrapper<"buyramburn"_n, &system_contract::buyramburn>;
using logramchange_action = eosio::action_wrapper<"logramchange"_n, &system_contract::logramchange>;
using refund_action = eosio::action_wrapper<"refund"_n, &system_contract::refund>;
using regproducer_action = eosio::action_wrapper<"regproducer"_n, &system_contract::regproducer>;
Expand All @@ -1534,19 +1588,12 @@ namespace eosiosystem {
using powerup_action = eosio::action_wrapper<"powerup"_n, &system_contract::powerup>;

private:
// Implementation details:

static symbol get_core_symbol( const rammarket& rm ) {
auto itr = rm.find(ramcore_symbol.raw());
check(itr != rm.end(), "system contract must first be initialized");
return itr->quote.balance.symbol;
}

//defined in eosio.system.cpp
static eosio_global_state get_default_parameters();
static eosio_global_state4 get_default_inflation_parameters();
symbol core_symbol()const;
void update_ram_supply();
void channel_to_system_fees( const name& from, const asset& amount );

// defined in rex.cpp
void runrex( uint16_t max );
Expand All @@ -1556,8 +1603,6 @@ 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, 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 );
template <typename T>
Expand All @@ -1567,8 +1612,6 @@ 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;
bool rex_system_initialized()const { return _rexpool.begin() != _rexpool.end(); }
bool rex_available()const { return rex_system_initialized() && _rexpool.begin()->total_rex.amount > 0; }
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 );
Expand Down
15 changes: 15 additions & 0 deletions contracts/eosio.system/ricardian/eosio.system.contracts.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,21 @@ Burn {{bytes}} bytes of unused RAM from account {{owner}}.
{{memo}}
{{/if}}

<h1 class="contract">buyramburn</h1>

---
spec_version: "0.2.0"
title: Buy and Burn RAM
summary: 'Buy and immediately Burn {{quantity}} of RAM from {{nowrap payer}}'
icon: @ICON_BASE_URL@/@RESOURCE_ICON_URI@
---

Buy and Burn {{quantity}} of RAM from account {{payer}}.

{{#if memo}}There is a memo attached to the action stating:
{{memo}}
{{/if}}

<h1 class="contract">sellrex</h1>

---
Expand Down
42 changes: 31 additions & 11 deletions contracts/eosio.system/src/delegate_bandwidth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ namespace eosiosystem {
check( quant.symbol == core_symbol(), "must buy ram with core token" );
check( quant.amount > 0, "must purchase a positive amount" );

auto fee = quant;
asset fee = quant;
fee.amount = ( fee.amount + 199 ) / 200; /// .5% fee (round up)
// fee.amount cannot be 0 since that is only possible if quant.amount is 0 which is not allowed by the assert above.
// If quant.amount == 1, then fee.amount == 1,
// otherwise if quant.amount > 1, then 0 < fee.amount < quant.amount.
auto quant_after_fee = quant;
asset quant_after_fee = quant;
quant_after_fee.amount -= fee.amount;
// quant_after_fee.amount should be > 0 if quant.amount > 1.
// If quant.amount == 1, then quant_after_fee.amount == 0 and the next inline transfer will fail causing the buyram action to fail.
Expand All @@ -72,7 +72,7 @@ namespace eosiosystem {
if ( fee.amount > 0 ) {
token::transfer_action transfer_act{ token_account, { {payer, active_permission} } };
transfer_act.send( payer, ramfee_account, fee, "ram fee" );
channel_to_rex( ramfee_account, fee );
channel_to_system_fees( ramfee_account, fee );
}

int64_t bytes_out;
Expand All @@ -91,13 +91,16 @@ namespace eosiosystem {

// logging
system_contract::logbuyram_action logbuyram_act{ get_self(), { {get_self(), active_permission} } };
logbuyram_act.send( payer, receiver, quant, bytes_out, ram_bytes );
system_contract::logsystemfee_action logsystemfee_act{ get_self(), { {get_self(), active_permission} } };

logbuyram_act.send( payer, receiver, quant, bytes_out, ram_bytes, fee );
logsystemfee_act.send( ram_account, fee, "buy ram" );

// action return value
return action_return_buyram{ payer, receiver, quant, bytes_out, ram_bytes };
return action_return_buyram{ payer, receiver, quant, bytes_out, ram_bytes, fee };
}

void system_contract::logbuyram( const name& payer, const name& receiver, const asset& quantity, int64_t bytes, int64_t ram_bytes ) {
void system_contract::logbuyram( const name& payer, const name& receiver, const asset& quantity, int64_t bytes, int64_t ram_bytes, const asset& fee ) {
require_auth( get_self() );
require_recipient(payer);
require_recipient(receiver);
Expand Down Expand Up @@ -134,23 +137,26 @@ namespace eosiosystem {
token::transfer_action transfer_act{ token_account, { {ram_account, active_permission}, {account, active_permission} } };
transfer_act.send( ram_account, account, asset(tokens_out), "sell ram" );
}
auto fee = ( tokens_out.amount + 199 ) / 200; /// .5% fee (round up)
const int64_t fee = ( tokens_out.amount + 199 ) / 200; /// .5% fee (round up)
// since tokens_out.amount was asserted to be at least 2 earlier, fee.amount < tokens_out.amount
if ( fee > 0 ) {
token::transfer_action transfer_act{ token_account, { {account, active_permission} } };
transfer_act.send( account, ramfee_account, asset(fee, core_symbol()), "sell ram fee" );
channel_to_rex( ramfee_account, asset(fee, core_symbol() ));
channel_to_system_fees( ramfee_account, asset(fee, core_symbol() ));
}

// logging
system_contract::logsellram_action logsellram_act{ get_self(), { {get_self(), active_permission} } };
logsellram_act.send( account, tokens_out, bytes, ram_bytes );
system_contract::logsystemfee_action logsystemfee_act{ get_self(), { {get_self(), active_permission} } };

logsellram_act.send( account, tokens_out, bytes, ram_bytes, asset(fee, core_symbol() ) );
logsystemfee_act.send( ram_account, asset(fee, core_symbol() ), "sell ram" );

// action return value
return action_return_sellram{ account, tokens_out, bytes, ram_bytes };
return action_return_sellram{ account, tokens_out, bytes, ram_bytes, asset(fee, core_symbol() ) };
}

void system_contract::logsellram( const name& account, const asset& quantity, int64_t bytes, int64_t ram_bytes ) {
void system_contract::logsellram( const name& account, const asset& quantity, int64_t bytes, int64_t ram_bytes, const asset& fee ) {
require_auth( get_self() );
require_recipient(account);
}
Expand Down Expand Up @@ -179,6 +185,20 @@ namespace eosiosystem {
return ramtransfer( owner, null_account, bytes, memo );
}

/**
* This action will buy and then burn the purchased RAM bytes.
*/
action_return_buyram system_contract::buyramburn( const name& payer, const asset& quantity, const std::string& memo ) {
require_auth( payer );
check( quantity.symbol == core_symbol(), "quantity must be core token" );
check( quantity.amount > 0, "quantity must be positive" );

const auto return_buyram = buyram( payer, payer, quantity );
ramburn( payer, return_buyram.bytes_purchased, memo );

return return_buyram;
}

[[eosio::action]]
void system_contract::logramchange( const name& owner, int64_t bytes, int64_t ram_bytes )
{
Expand Down
Loading

0 comments on commit 47e44bd

Please sign in to comment.