From 9dd2717699b8dc822e6874538431074dae863769 Mon Sep 17 00:00:00 2001 From: Denis Carriere Date: Thu, 25 Jan 2024 17:16:21 -0500 Subject: [PATCH] Implement `buyramself` action ref: https://github.com/eosnetworkfoundation/eos-system-contracts/issues/105 --- .../include/eosio.system/eosio.system.hpp | 11 +++++++++++ .../ricardian/eosio.system.contracts.md.in | 11 +++++++++++ .../eosio.system/src/delegate_bandwidth.cpp | 6 ++++++ tests/eosio.system_ram_tests.cpp | 16 ++++++++++++++++ tests/eosio.system_tester.hpp | 4 ++++ 5 files changed, 48 insertions(+) diff --git a/contracts/eosio.system/include/eosio.system/eosio.system.hpp b/contracts/eosio.system/include/eosio.system/eosio.system.hpp index 887a899b..be88f739 100644 --- a/contracts/eosio.system/include/eosio.system/eosio.system.hpp +++ b/contracts/eosio.system/include/eosio.system/eosio.system.hpp @@ -1110,6 +1110,17 @@ namespace eosiosystem { [[eosio::action]] void buyrambytes( const name& payer, const name& receiver, uint32_t bytes ); + /** + * The buyramself action is designed to enhance the permission security by allowing an account to purchase RAM exclusively for itself. + * This action prevents the potential risk associated with standard actions like buyram and buyrambytes, + * which can transfer EOS tokens out of the account, acting as a proxy for eosio.token::transfer. + * + * @param account - the ram buyer and receiver, + * @param quant - the quantity of tokens to buy ram with. + */ + [[eosio::action]] + void buyramself( const name& account, const asset& quant ); + /** * Logging for buyram & buyrambytes action * diff --git a/contracts/eosio.system/ricardian/eosio.system.contracts.md.in b/contracts/eosio.system/ricardian/eosio.system.contracts.md.in index 24e896a6..d82a209b 100644 --- a/contracts/eosio.system/ricardian/eosio.system.contracts.md.in +++ b/contracts/eosio.system/ricardian/eosio.system.contracts.md.in @@ -59,6 +59,17 @@ icon: @ICON_BASE_URL@/@RESOURCE_ICON_URI@ {{payer}} buys RAM on behalf of {{receiver}} by paying {{quant}}. This transaction will incur a 0.5% fee out of {{quant}} and the amount of RAM delivered will depend on market rates. +

buyramself

+ +--- +spec_version: "0.2.0" +title: Buy RAM self +summary: '{{nowrap account}} buys RAM to self by paying {{nowrap quant}}' +icon: @ICON_BASE_URL@/@RESOURCE_ICON_URI@ +--- + +{{account}} buys RAM to self by paying {{quant}}. This transaction will incur a 0.5% fee out of {{quant}} and the amount of RAM delivered will depend on market rates. +

buyrambytes

--- diff --git a/contracts/eosio.system/src/delegate_bandwidth.cpp b/contracts/eosio.system/src/delegate_bandwidth.cpp index d21a9650..86533822 100644 --- a/contracts/eosio.system/src/delegate_bandwidth.cpp +++ b/contracts/eosio.system/src/delegate_bandwidth.cpp @@ -31,6 +31,12 @@ namespace eosiosystem { buyram( payer, receiver, asset{ cost_plus_fee, core_symbol() } ); } + /** + * Buy self ram action, ram can only be purchased to itself. + */ + void system_contract::buyramself( const name& account, const asset& quant ) { + buyram( account, account, quant ); + } /** * When buying ram the payer irreversibly transfers quant to system contract and only diff --git a/tests/eosio.system_ram_tests.cpp b/tests/eosio.system_ram_tests.cpp index df0948ef..984394f6 100644 --- a/tests/eosio.system_ram_tests.cpp +++ b/tests/eosio.system_ram_tests.cpp @@ -63,4 +63,20 @@ BOOST_FIXTURE_TEST_CASE( ram_burn, eosio_system_tester ) try { } FC_LOG_AND_RETHROW() + +// buyramself +BOOST_FIXTURE_TEST_CASE( buy_ram_self, eosio_system_tester ) try { + const std::vector accounts = { "alice"_n }; + create_accounts_with_resources( accounts ); + const account_name alice = accounts[0]; + + transfer( config::system_account_name, alice, core_sym::from_string("100.0000"), config::system_account_name ); + const uint64_t alice_before = get_total_stake( alice )["ram_bytes"].as_uint64(); + BOOST_REQUIRE_EQUAL( success(), buyramself( alice, core_sym::from_string("1.0000")) ); + const uint64_t alice_after = get_total_stake( alice )["ram_bytes"].as_uint64(); + BOOST_REQUIRE_EQUAL( alice_before + 68375, alice_after ); + +} FC_LOG_AND_RETHROW() + + BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/eosio.system_tester.hpp b/tests/eosio.system_tester.hpp index a3a3e853..c839e2fb 100644 --- a/tests/eosio.system_tester.hpp +++ b/tests/eosio.system_tester.hpp @@ -281,6 +281,10 @@ class eosio_system_tester : public TESTER { return sellram( account_name(account), numbytes ); } + action_result buyramself( const account_name& account, const asset& quant ) { + return push_action( account, "buyramself"_n, mvo()( "account",account)("quant",quant) ); + } + action_result push_action( const account_name& signer, const action_name &name, const variant_object &data, bool auth = true ) { string action_type_name = abi_ser.get_action_type(name);